【Svelte从入门到精通】实战篇——Alert组件之slot交互

api

接下来我们完成剩余的api,主要有afterClose回调、closeText、description、icon、message。

在Svelte中,我们不能像react那样直接把组件当成一个props来传递,因此对于一些既支持传数据又支持传组件的参数,我们的在Svelte的实现是既支持传值,又支持slot定义。然后在组件内容判断是否有slot值。

javascript 复制代码
function getPropsSlot(slots, props, prop = 'default') {
  if (props && props[prop]) {
    return props[prop];
  }
  if (slots && slots[prop]) {
    return slots[prop];
  }
  return null;
}
const slots = $$slots;
const props = $$props;

closeText

javascript 复制代码
export let closeText = undefined;

const closeTextData = getPropsSlot(slots, props, 'closeText');
const hasCloseTextSlot = !!slots?.closeText;

if (closeTextData) {
  closable = true;
}

修改html的内容

html 复制代码
{#if closable}
  <a
    href={""}
    on:click|preventDefault={handleClose}
    class={`${prefixCls}-close-icon`}
    role="button"
    tabindex="0"
  >
    {#if hasCloseTextSlot}
      <slot name="closeText" />
    {:else if closeTextData}
      {closeText}
    {:else}
      <i class={`anticon anticon-close ${prefixCls}-icon`}>
        <CloseIcon />
      </i>
    {/if}
  </a>
{/if}

App.svelte中试验一下:

html 复制代码
<script>
  import Alert from "./Alert.svelte";
</script>

<Alert closeText="Close Text">Text</Alert>
<br />
<Alert type="success">
  Text
  <div slot="closeText">Close Text2</div>
</Alert>
<br />

message

javascript 复制代码
export let message = undefined;
const messageData = getPropsSlot(slots, props, 'message');
const hasMessageSlot = !!slots?.message;

修改我们最开始定义的slot

html 复制代码
<div class={`${prefixCls}-content`}>
    {#if showIcon}
    <i class={`anticon ${prefixCls}-icon`}>
      <svelte:component this={icon} />
    </i>
    {/if}
    {#if messageData}
      {#if hasMessageSlot}
            <slot name="message" />
      {:else}
            <div class={`${prefixCls}-message`}>{message}</div>
      {/if}
    {/if}
</div>

在App.svelte中试验一下:

html 复制代码
<script>
  import Alert from "./Alert.svelte";
</script>

<Alert closable message="message" />
<br />
<Alert type="success" closable>
  <div slot="message" style="color: red;">message2</div>
</Alert>
<br />

description

javascript 复制代码
export let description = undefined;
const descriptionData = getPropsSlot(slots, props, 'description');
const hasDescriptionSlot = !!slots?.description;

在Antd的Alert组件中,当使用了description时,需要使用另一种样式的icon,为此我们需要重构下我们的icon组件,笔者这里只拿SuccessIcon作为例子,其他type的icon更改逻辑相同。

SuccessIcon.svelte:

html 复制代码
<script>
  export let theme = "filled";
</script>

{#if theme === "filled"}
  <svg
    viewBox="64 64 896 896"
    focusable="false"
    class=""
    data-icon="check-circle"
    width="1em"
    height="1em"
    fill="currentColor"
    aria-hidden="true"
    ><path
      d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm193.5 301.7l-210.6 292a31.8 31.8 0 0 1-51.7 0L318.5 484.9c-3.8-5.3 0-12.7 6.5-12.7h46.9c10.2 0 19.9 4.9 25.9 13.3l71.2 98.8 157.2-218c6-8.3 15.6-13.3 25.9-13.3H699c6.5 0 10.3 7.4 6.5 12.7z"
    ></path></svg
  >
{/if}
{#if theme === "outlined"}
  <svg
    viewBox="64 64 896 896"
    focusable="false"
    class=""
    data-icon="check-circle"
    width="1em"
    height="1em"
    fill="currentColor"
    aria-hidden="true"
    ><path
      d="M699 353h-46.9c-10.2 0-19.9 4.9-25.9 13.3L469 584.3l-71.2-98.8c-6-8.3-15.6-13.3-25.9-13.3H325c-6.5 0-10.3 7.4-6.5 12.7l124.6 172.8a31.8 31.8 0 0 0 51.7 0l210.6-292c3.9-5.3.1-12.7-6.4-12.7z"
    ></path><path
      d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"
    ></path></svg
  >
{/if}
javascript 复制代码
let iconTheme = 'filled';

if (!!descriptionData) {
  iconTheme = 'outlined';
}
javascript 复制代码
$: alertCls = classNames(prefixCls, {
    [`${prefixCls}-${type}`]: true,
    [`${prefixCls}-no-icon`]: !showIcon,
    [`${prefixCls}-banner`]: banner,
    [`${prefixCls}-closable`]: closable,
    [`${prefixCls}-with-description`]: !!descriptionData,
});

在App.svelte中试验下

html 复制代码
<script>
  import Alert from "./Alert.svelte";
</script>

<Alert
  message="Success Tips"
  description="Detailed description and advice about successful copywriting."
  type="success"
  showIcon
/>
<br />
<Alert message="Infomation Tips" showIcon>
  <div slot="description">
    Additional description and information about copywriting.
  </div>
</Alert>

icon

javascript 复制代码
const hasIconSlot = !!slots?.icon;

修改html内容

html 复制代码
{#if showIcon}
  {#if hasIconSlot}
	<slot name="icon" />
  {:else}
	<i class={`anticon ${prefixCls}-icon`}>
	  <svelte:component this={icon} theme={iconTheme} />
	</i>
  {/if}
{/if}

我们自定义一个Icon组件,笔者这里就不列出这部分代码了,读者朋友们可以自行定义。 在App.svelte中验证一下

html 复制代码
<script>
  import Alert from "./Alert.svelte";
  import SvelteIcon from "./icon/SvelteIcon.svelte";

</script>

<Alert
  message="Success Tips"
  type="success"
  showIcon
>
  <SvelteIcon slot="icon" />
</Alert>

我们还剩余一部分内容,那就是关闭时的动画,在下一章中进行讲解。

小结

本章我们完成了:

  • $$props$$slots的使用
  • <slot>插槽的使用
相关推荐
逐·風3 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
Devil枫3 小时前
Vue 3 单元测试与E2E测试
前端·vue.js·单元测试
尚梦4 小时前
uni-app 封装刘海状态栏(适用小程序, h5, 头条小程序)
前端·小程序·uni-app
GIS程序媛—椰子4 小时前
【Vue 全家桶】6、vue-router 路由(更新中)
前端·vue.js
前端青山5 小时前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
毕业设计制作和分享5 小时前
ssm《数据库系统原理》课程平台的设计与实现+vue
前端·数据库·vue.js·oracle·mybatis
从兄6 小时前
vue 使用docx-preview 预览替换文档内的特定变量
javascript·vue.js·ecmascript
清灵xmf7 小时前
在 Vue 中实现与优化轮询技术
前端·javascript·vue·轮询
大佩梨7 小时前
VUE+Vite之环境文件配置及使用环境变量
前端
GDAL7 小时前
npm入门教程1:npm简介
前端·npm·node.js