大部分场景其实不需要 Slot,但是如果你想实现一个 UI 库,似乎绕不开它。
简单来说,我们给组件传数据是非常自由的,可以传各种类型的数据,但是如果你想传 DOM,现有的机制是做不到的。
因此,我们设计了一套比较灵活的传 DOM 机制,而它是专门为组件服务的。
<Component>
text
</Component>
在上面的例子中,我们仅仅给组件传了一个字符串。
如果你希望字符串旁边加个图标,可以这么做:
<Component>
<i class="icon-info"></i>
text
</Component>
在组件的模板中,你希望获取外部传入的这个 DOM,可以这么取:
<button>
<slot name="children" />
</button>
这里出现了一个模式的 slot 标签,不要惊慌,这个标签的作用仅仅是用来取外部传入的 DOM(不然你发明一个更自然的语法来看看啊)。
至于这个 slot 的 name 为啥叫做 children
,没办法,如果你没取名字,默认就叫做 children
。
下面讲解怎么给 slot 取名字。
有时候,你希望传入多个 DOM,比如左边一个图标,右边一个图标:
<Component>
<template slot="left">
<i class="icon-left"></i>
</template>
<template slot="right">
<i class="icon-right"></i>
</template>
text
</Component>
这里的重点是 template 标签,它的作用仅仅是声明一个 slot,并用 slot 属性取名字,方便在组件内部引用。
为什么要单独用一个 template 标签呢?主要考虑可能传入多个元素。
此外,大家可能注意到这里还有个孤零零的 text,它并非是多余的,我们的初衷是,如果组件标签内部定义的模板没有名字,那它统统属于 children
。
我们知道了 slot 的命名机制,在实际使用中,通常还需要判断是否存在该 slot,换句话说,父组件是否往下传了该 slot 呢?
为此,我们添加了一个全局过滤器,使用方式如下:
<div>
{{#if hasSlot('slot 的名字')}}
存在
{{else}}
不存在
{{/if}}
</div>