插槽就是子组件中的提供给父组件使用的一个占位符,用 <slot></slot> 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的 <slot></slot> 标签。简单理解就是子组件中留下个“坑”,父组件可以使用指定内容来补“坑”。
当结构需要定制化时,我们会大量使用到插槽!!!本文从匿名插槽、插槽后备内容、具名插槽、作用域插槽4方面着手,360度无死角的介绍插槽:
1. 匿名插槽
步骤1:子组件中使用 <slot> 占位,例如在 my-dialog.vue 中 (挖坑)
<template>
<div class="dialog">
<h3>友情提示:</h3>
<slot />
<button>关闭</button>
</div>
</template>
步骤2:在使用组件的位置填充内容,例如 App.vue 中 (填坑)
<template>
<div>
<my-dialog>
<p>请输入正确的手机号码!</p>
</my-dialog>
</div>
</template>
<script>
import myDialog from './components/my-dialog.vue'
export default {
components: { myDialog }
}
</script>
结果:<p>请输入正确的手机号码!</p> 这个HTML结构,直接替换 <slot />
2. 插槽后备内容
可以给插槽提供后备内容,如果使用组件的时候没有填坑,就展示插槽的后备内容。
# 子组件
<template>
<div class="dialog">
<h3>友情提示:</h3>
<slot>
# 我是后备内容
<p>我是缺省文字!</p>
</slot>
<button>关闭</button>
</div>
</template>
# 根组件
<template>
<div>
# 啥也没传, 显示后备内容
<my-dialog />
</div>
</template>
3. 具名插槽
具名插槽就是有名字的插槽,当一个组件内有多处需要外部传入标签进行定制化,就到了具名插槽表演的时机。
步骤1:子组件内,多个 slot 使用 name 属性区分名字
# 例如 my-dialog.vue 中
<template>
<div class="dialog">
<slot name="header" />
<slot name="content" />
<slot name="footer" />
</div>
</template>
步骤2:根组件内,使用 <template> 配合 v-slot:名字 来分发对应标签,v-slot:名字 可以简化成 #名字
# 例如 App.vue 中
<my-dialog>
<template #header>
<h3>温馨提示: </h3>
</template>
<template #content>...</template>
<template #footer>...</template>
</my-dialog>
4. vue提供的具名插槽 default
vue默认提供了一个名字为 default 的具名插槽,偶尔也会用到
# 子组件里
<template>
<div class="dialog">
<slot name="header" />
# 这里故意不写name,不写name, name默认就是default
<slot />
<slot name="footer" />
</div>
</template>
# 根组件里
<template>
<div>
<my-dialog>
<template #header>...</template>
# 对应上面故意不写name的slot
<template #default>...</template>
<template #footer>...</template>
</my-dialog>
</div>
</template>
5. 作用域插槽
作用域插槽就是携带了数据的插槽,有点像组件通讯中的“子传父”。
步骤1:子组件内,设置 <slot> 标签,以添加属性的方式传值
步骤2:所有添加的属性,都会被收集到一个对象中
步骤3:在根组件内,在 <template> 标签上,通过 #插槽名 = "props" 接收
# 子组件里
<template>
<div class="dialog">
<slot name="content" :list="list" />
</div>
</template>
<script>
export default {
data(){
return {
list: [
{ id: 1, name: '苹果' },
{ id: 2, name: '橘子' },
{ id: 3, name: '香蕉' }
]
}
}
}
</script>
# 父组件里
<template>
<div>
<my-dialog>
# 在插槽上携带的数据, 会被收集到一个对象中, 通常进行解构
<template #content="{ list }">
<p v-for="item in list " :key="item.id">
{{ item.name }}
</p>
</template>
</my-dialog>
</div>
</template>
End--------------------------