- 什么是插槽?
插槽是父组件可以向子组件传递一些模板内容,让子组件在父组件中渲染这些片段。
vue中的slot 元素是一个插槽出口,标识了父元素提供的插槽内容显示的位置 - 插槽分类
- 默认插槽
可以为插槽提供默认内容,父组件没有传递内容,默认内容会显示,传递了内容,则会覆盖插槽的默认内容
子组件 SlotSon
<template> <div> 我是插槽 <slot> <!-- 为插槽提供默认内容 --> 子插槽 </slot> </div>
- 默认插槽
<template>
<div>
<slotSon>
<!-- 父组件提供了内容,默认内容会被覆盖 ,若不提供内容,默认内容会显示 -->
我是父亲
</slotSon>
</div>
</template>
-
具名插槽
- 一个组件含有多个插槽出口,为了分清插入的位置, 元素有一个特殊的 attribute (name),来给每个插槽分配唯一的 ID,以确定每一处要渲染的内容
- 插槽名字的定义 没有name属性的默认name为default
子组件:
父组件使用插槽:<template> <div> <-- 名字默认为default --> <slot>默认内容</slot> <slot name="header">我是header</slot> <slot name="main">我是内容</slot> <slot name="footer">我是footer</slot> </div> </template>
我们需要一种方式将多个插槽内容传入到各自目标插槽的出口,此时就需要用到具名插槽了:
要为具名插槽传入内容,我们需要使用一个含 v-slot 指令的 元素,并将目标插槽的名字传给该指令:<template> <div> <slotSon> <!-- <template v-slot:header> v-slot:header 和#header 是等价的,v-slot可以简写为# --> <template #header> <div class="header">header</div> </template> <template #main> <div class="main">main</div> </template> <template #footer> <div class="footer">footer</div> </template> <!-- 会插入到默认插槽,也就是没有名字的插槽,或者name为default的 --> 123456 </slotSon> </div> </template>
-
动态插槽名
插槽名为变量的写法<template> <div> <slotSon> <!-- obj.name 就是header --> <template #[obj.name]="{content}"> <div class="header" v-for="item in content" :key="item.id">{{item.name}}</div> </template> </slotSon> </div> </template> <script setup> import slotSon from './slotSon' let obj = { name:'header' } </script>
-
作用域插槽
子组件的插槽要传数据到父组件
默认插槽传值 子组件 MyComponent``` <div> <slot :text="greetingMessage" :count="1"></slot> </div>
父组件接收值
<MyComponent v-slot="slotProps"> {{ slotProps.text }} {{ slotProps.count }} </MyComponent>
起名字的插槽传值 子组件 slotSon
<template>
<div>
<!-- 名字默认为default -->
<slot :content="defaultObj">默认内容</slot>
<slot name="header" :content = "headObj">我是header</slot>
<slot name="main" :content = "main">我是内容</slot>
<slot name="footer" :content="footer">我是footer</slot>
</div>
</template>
<script>
import {ref,reactive} from 'vue'
export default {
name:'slotSon',
setup(){
let defaultObj = ref("默认插槽")
let headObj = reactive([{
id:'001',
name:'jerry'
},{
id:'002',
name:'Tom'
}])
let main = ref("主页")
let footer = reactive([{
id:'005',
content:'感谢赞助商'
},{
id:'006',
content:'感谢关心我的人'
}])
return{
defaultObj,
headObj,
main,
footer
}
}
}
</script>
父组件获取值:
<template>
<div>
<slotSon>
<!-- <template v-slot:header> v-slot:header 和#header 是等价的,v-slot可以简写为# -->
<!-- <template #default>
default
</template> -->
<!-- {content}是解构赋值 #main="value" value是slot传的值都在value里面,格式为value = {content:值} -->
<template #header="{content}">
<div class="header" v-for="item in content" :key="item.id">{{item.name}}</div>
</template>
<template #main="{content}">
<div class="main">{{content}}</div>
</template>
<template #footer="{content}">
<div class="footer" v-for="item in content" :key="item.id">{{item.content}}</div>
</template>
<!-- 会插入到默认插槽,也就是没有名字的插槽,或者name为default的 -->
<template v-slot="{content}">
123456
{{content}}
</template>
</slotSon>
</div>
</template>
作用域插槽的使用场景:
1.要渲染一个列表,并同时会封装一些加载远端数据的逻辑、使用数据进行列表渲染、或者是像分页或无限滚动这样更进阶的功能,然而我们希望它能够保留足够的灵活性,将对单个列表元素内容和样式的控制权留给使用它的父组件,这时,就要用到作用域插槽来传递值
2.一些组件可能只包括了逻辑而不需要自己渲染内容,视图输出通过作用域插槽全权交给了消费者组件