插槽,也就是slot,slot就是子组件里的一个占位符。这个占位符的内容由父组件控制,父组件往这个子组件模板里面传入什么内容,则这个占位符显示什么内容。
应用领域:插槽在写通用组件这块简直就是神器,尤其是像一些UI组件库,比如ElementUI 组件库,Ant Design UI 组件库。
在 2.6.0 中,我们为具名插槽和作用域插槽引入了一个新的统一的语法 (即
v-slot指令)。它取代了slot和slot-scope这两个目前已被废弃但未被移除且仍在文档中的 attribute。新语法的由来可查阅这份 RFC。
插槽有三种类型的: 匿名插槽、具名插槽、作用域插槽。
匿名插槽
匿名插槽的name值,其实是default。
假如我们现在要写通用的模态窗组件:
子组件代码:modal1.vue
<template>
<div class="slot-modal">
<!-- 匿名插槽 -->
<div class="default">
<div class="title">{{title}}</div>
<div class="content">
<slot></slot>
</div>
<div class="footer">
<a-button>{{cancelText}}</a-button>
<a-button>{{confirmText}}</a-button>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
title: {
type: String,
default: '标题'
},
cancelText: {
type: String,
default: '取消'
},
confirmText: {
type: String,
default: '确定'
}
}
}
</script>
上面子组件的slot标签,是一个占位符,内容由父组件控制,父组件在调用子组件的时候,传入什么内容,则子组件显示什么内容。
这样使用的话,这个slot就叫做插槽。这种插槽没有名称,也叫做匿名插槽
父组件代码:
<template>
<div>
<modal1
title="title"
cancelText="cancel"
confirmText="ok"
>
这是modal内容
</modal1>
</div>
</template>
父组件在使用子组件modal1的时候,直接传入了内容'这是modal内容',内容将直接通过子组件的插槽显示出来。效果图:
具名插槽
有时我们一个组件里面需要多个插槽。我们怎么来区分多个slot,而且不同slot的显示位置也是有差异的.对于这样的情况, 元素有一个特殊的特性:name。这个特性可以用来定义额外的插槽:
- 注意:一个不带 name 的 出口会带有隐含的名字“default”。就是说,匿名插槽的name值,其实是default
下面依旧写一个模态窗,不过内容区域有两块,一个主内容,一个副内容。
子组件代码:modal2.vue
<template>
<div class="slot-modal">
<!-- 具名插槽 -->
<div class="default">
<div class="title">
{{title}}
</div>
<div class="content">
<slot name="content1">主内容</slot>
<slot name="content2">副内容</slot>
</div>
<div class="footer">
<a-button>
{{cancelText}}
</a-button>
<a-button>
{{confirmText}}
</a-button>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
title: {
type: String,
default: '标题'
},
cancelText: {
type: String,
default: '取消'
},
confirmText: {
type: String,
default: '确定'
}
}
}
</script>
上面定义了两个插槽 ,name分别为‘content1’,'content2',下面开始使用这两个插槽:
在向具名插槽提供内容的时候,我们可以在一个 <template> 元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称:
<template>
<div>
<modal2 title="title" cancelText="cancel" confirmText="ok">
<template v-slot:content1>
<h2>内容1</h2>
</template>
<template #content2>
<p>内容2</p>
</template>
</modal2>
</div>
</template>
注意 v-slot 只能添加在 <template> 上 (只有一种例外情况),这一点和已经废弃的 slot attribute 不同。
具名插槽的缩写:
2.6.0 新增
跟 v-on 和 v-bind 一样,v-slot 也有缩写,即把参数之前的所有内容 (v-slot:) 替换为字符 #。例如 v-slot:header 可以被重写为 #header
作用域插槽
自 2.6.0 起有所更新。已废弃的使用 slot-scope 特性的语法在这里。
有时候,插槽的内容中有需要访问到子组件里面的内容,类似子组件里的slot可以绑定一些当前作用域,从而传出来,使用组件时,插槽的内容就可以拿到slot传出来的数据,父级的插槽内容可用。
如下是子组件myTable.vue,我们想把 item.name 在父组件中替换成 item.englishName
<template>
<div class="tb">
<table border="1">
<tr>
<th>编号</th>
<th>名称</th>
<th>价格</th>
</tr>
<tr v-for="item in fruits" :key="item.id">
<td>{{ item.id }}</td>
<td>
<slot name="table" :slotfruits="fruits" test="123">{{ item.name }}</slot>
</td>
<td>{{ item.price }}</td>
</tr>
</table>
</div>
</template>
<script>
export default {
data(){
return {
fruits: [
{
id: 1,
name: '苹果',
englishName: 'apple',
price: 5
},
{
id: 2,
name: '香蕉',
englishName: 'banana',
price: 8
}
]
}
}
}
</script>
绑定在 元素上的特性被称为插槽 prop,我们在子组件中绑定属性,:slotProps="fruits",test="123"
在父组件中,我们可以访问到这些绑定的属性。 如下父组件:
<my-table>
<template #table="a">
{{a.slotProps.englishName}}
</template>
</my-table>
在父组件中,我们可以通过 v-slot:插槽名=自定义名,来获取子组件插槽传递过来的值。a的值是:
{
"slotProps": {
"id": 1,
"name": "苹果",
"englishName": "apple",
"price": 5
},
"test": "123"
}
这样,子组件向父组件传递值的方式又多了一种,即作用域插槽的方式。
效果图:
废弃的语法:
在 2.6.0 中,我们为具名插槽和作用域插槽引入了一个新的统一的语法 (即
v-slot指令)。它取代了slot和slot-scope这两个目前已被废弃但未被移除且仍在文档中的 attribute。新语法的由来可查阅这份 RFC。在vue3版本旧语法被移除。
在2.6.0版本之前,语法是这样的写法:
<template slot="default" slot-scope="slotProps">
{{ slotProps.msg }}
</template>
新语法和旧语法写法对比:
<template>
<a-result>
<!-- slot新语法 -->
<template v-slot:title>
<p>您没有权限哦~</p>
</template>
<!-- 新语法 缩写 -->
<template #subTitle>
<p>请联系管理员或者联系客服哈</p>
</template>
<!-- slot旧语法 -->
<template slot="icon">
<a-icon type="meh" />
</template>
<template slot="extra">
<a-button>返回首页</a-button>
</template>
</a-result>
</template>