Vue组件之Slots分发内容

介绍

在使用组件时,父组件中的内容会被丢弃,比如:

1
2
3
<my-component>
<p>这是一些内容</p>
</my-component>

组件my-component中的p标签是不会被渲染的,但实际开发中,我们可能希望运用到父组件中的内容,因为在使用组件时,常常需要这样组合它们:

1
2
3
4
<app>
<app-header></app-header>
<app-footer></app-footer>
</app>

为了让组件可以组合,我们需要一种方式来混合父组件的内容与子组件自己的模板。这个过程被称为 内容分发,vue提供了一个API,使用特殊的<slot>元素作为原始内容的插槽。

单个Slot

要想使用父组件的内容,需要在子组件中加入<slot>插口。

假设 my-component 组件有下面模板:

1
2
3
4
5
6
7
<div>
<h3>我是子组件的标题</h3>
<p>我是子组件的内容</p>
<slot>
只有在没有要分发的内容时才会显示。
</slot>
</div>

父组件模板:

1
2
3
4
5
<h2>我是父组件的标题</h2>
<hr>
<my-component>
<p>我是父组件的内容</p>
</my-component>

渲染结果:

1
2
3
4
5
6
7
<h2>我是父组件的标题</h2>
<hr>
<div>
<h3>我是子组件的标题</h3>
<p>我是子组件的内容</p>
<p>我是父组件的内容</p>
</div>

可知,父组件中的内容被渲染到子组件的slot插口所在的DOM位置,并替换掉slot标签本身。

说明:

当子组件模板只有一个没有属性的 slot 时,父组件整个内容片段将插入到 slot 所在的 DOM 位置,并替换掉 slot 标签本身

最初在<slot>标签中的任何内容都被视为备用内容,在父组件中无内容时显示。

具名Slot

元素可以用一个特殊的属性 name 来配置如何分发内容。多个 slot 可以有不同的名字。具名 slot 将匹配内容片段中有对应 slot 特性的元素。

例子:

父组件模板:

1
2
3
4
5
6
7
8
9
10
11
12
<my-component>

<p slot="one">这是替换第一个内容</p>

<template slot="two">
<p>替换第二个内容</p>
<span>一个span标签,替换第二个内容</span>
</template>

<p slot="three">这是替换第三个内容</p>

</my-component>

子组件模板:

1
2
3
4
5
6
<div>

<slot name="one"><p>这是子组件第1个内容</p></slot>
<slot name="two"><p>这是子组件第2个内容</p></slot>
<slot name="three"><p>这是子组件第3个内容</p></slot>
</div>

渲染结果:

1
2
3
4
<p>这是替换第一个内容</p>
<p>替换第二个内容</p>
<span>一个span标签,替换第二个内容</span>
<p>这是替换第三个内容</p>