Vue中的插槽
插槽就是子组件中的提供给父组件使用的一个占位符,用 <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--------------------------