【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>插槽的使用
相关推荐
九月十九20 分钟前
AviatorScript用法
java·服务器·前端
Jane - UTS 数据传输系统43 分钟前
VUE+ Element-plus , el-tree 修改默认左侧三角图标,并使没有子级的那一项不展示图标
javascript·vue.js·elementui
_.Switch1 小时前
Python Web开发:使用FastAPI构建视频流媒体平台
开发语言·前端·python·微服务·架构·fastapi·媒体
菜鸟阿康学习编程2 小时前
JavaWeb 学习笔记 XML 和 Json 篇 | 020
xml·java·前端
索然无味io2 小时前
XML外部实体注入--漏洞利用
xml·前端·笔记·学习·web安全·网络安全·php
ThomasChan1233 小时前
Typescript 多个泛型参数详细解读
前端·javascript·vue.js·typescript·vue·reactjs·js
爱学习的狮王3 小时前
ubuntu18.04安装nvm管理本机node和npm
前端·npm·node.js·nvm
东锋1.33 小时前
使用 F12 查看 Network 及数据格式
前端
zhanggongzichu3 小时前
npm常用命令
前端·npm·node.js
anyup_前端梦工厂3 小时前
从浏览器层面看前端性能:了解 Chrome 组件、多进程与多线程
前端·chrome