Vue系列 | 插槽Slot

Slot背景知识

slot:在英文中名词有位置,入口的意思,而动词有插入的意思。在W3C的webcomponents,给出了slot的定义:

1
a defined locaiton in a shadow tree,Represented by the <slot> element。

表面理解插槽即位置,是用来在阴影树中定义位置的。表现形式为标签形式,即<slot>

slot name:the name of a slot 插槽的名字

default slot:a slot for assigning nodes without a slot name 即分配到节点上的匿名插槽。

Slotting Algorithm : 将阴影树中的主机节点分配到slots中。具体内容可以查看原文档。

Vue中的Slot

参考:Slots

有了刚刚的背景知识,我们就比较好理解Vue中的插槽了。即Vue中的内容分发API,表现形式也依然是以<slot>元素的形式作为内容分发的出口。即它是用来做内容分发的,具体怎么做。我们来看:

实例参考:Vue插槽详解

我们创建一个HTML文件,引入Vue,而后创建子组件child-component,并声明使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<html>
<header>
</header>
<body>
<div id="app">
<child-component>你好</child-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script type="text/javascript">
Vue.component('child-component',{
template:'<div>Hello world!</div>'
})
new Vue({
el:'#app',
})
</script>
</body>
</html>
// 打印:Hello world!

主页子组件中的“你好”没显示,现在我们在子组件中做如下修改:

1
2
3
4
Vue.component('child-component',{
template:'<div>Hello world! <slot></slot></div>'
})
// 打印:Hello world!你好

这就是插槽的作用,这就是所谓的内容分发,通过<slot>元素的形式,把子组件之间的内容分发到slot所在的位置。

具名插槽

就是给插槽的元素起个名字,而使用的时候要使用<template slot="xxx">的形式引用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<body>
<div id="app">
<child-component>
<template slot="girl">
女号
</template>
你好
</child-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script type="text/javascript">
Vue.component('child-component',{
template:'<div>Hello world!<slot name="girl"></slot> <slot></slot></div>'
})
new Vue({
el:'#app',
})
</script>
</body>
// 打印:Hello world! 女号 你好

作用域插槽

即子组件slot元素上的属性可以在引用该组件的嵌套范围内使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<body>
<div id="app">
<child-component>
<template slot="girl">
女号
</template>
<template slot-scope="test">
{{ test }}
</template>
你好
</child-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script type="text/javascript">
Vue.component('child-component',{
template:'<div>Hello world!<slot name="girl"></slot> <slot say="吃了吗"></slot></div>'
})
new Vue({
el:'#app',
})
</script>
</body>
// 打印:Hello world! 女号 { "say": "吃了吗" }

即作用域插槽将slot内的属性以键值对的方式打印出来了。

这是一个有用的功能,我们可以利用拿到的数据写一些逻辑了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<child-component>
<template slot="girl">
女号
</template>
<template slot-scope="test">
<div v-if="test.say == '吃了吗'">
吃了
</div>
</template>
你好
</child-component>
// 打印 :
// Hello world! 女号
// 吃了

是不是很熟悉呢,这就是ElementUI中Table的操作区的传值用法。

1
2
3
4
5
6
7
8
9
10
<el-table-column>
<template slot-scope="scope">
<el-button
@click.native.prevent="deleteRow(scope.$index, rowData)"
type="text"
size="small">
Remove
</el-button>
</template>
</el-table-column>