插槽就是子组件中的提供给父组件使用的一个占位符,用 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的 标签。这也是父子间传值的一种方式
1. 默认插槽
子组件中
<template>
<!-- 插槽占位符,可以有多个,每个的内容都会相同 -->
<slot></slot>
<slot></slot>
<slot></slot>
</template>
父组件中
规范写法:v-slot 表明这里使用 默认插槽,有且只能有一个,并且只能使用在 components or <template> 上
<template>
<child-slot>
<template v-slot>
<div>
111
</div>
</template>
</child-slot>
</template>
<script setup lang="ts">
import ChildSlot from './components/ChildSlot.vue'
</script>
不规范写法:不写 v-slot,不用 <template>(如果不写 v-slot,用了 <template> 也显示不出来内容)
那么 <child-slot> 可以包裹任何内容,均能显示出来
2. 具名插槽
子组件中
<!-- 可以看到,默认插槽只能有一个,而具名插槽可以有多个,并且用 name 来命名 -->
<template>
<slot name="header"></slot>
<slot></slot>
<slot name="footer"></slot>
</template>
父组件中
<!-- 父组件中,默认插槽用 v-slot 来标识,具名插槽用 v-slot:name 来标识 -->
<!-- 简写形式:默认插槽用 #default 来标识,具名插槽用 #name 来标识 -->
<template>
<child-slot>
<template v-slot:header>
<div>
顶部 —— 具名插槽
</div>
</template>
<template v-slot>
<div>
中间 —— 默认插槽
</div>
</template>
<template v-slot:footer>
<div>
底部 —— 匿名插槽
</div>
</template>
</child-slot>
</template>
3. 动态插槽
子组件中
<template>
<slot name="dynamic1"></slot>
<slot name="dynamic2"></slot>
</template>
父组件中
<template>
<child-slot>
<!-- 换成变量名,可动态切换插槽名称 -->
<template #[name]>
<div>
动态插槽:{{ name }}
</div>
</template>
</child-slot>
<button @click="changeSlot">更换插槽</button>
</template>
<script setup lang="ts">
import ChildSlot from './components/ChildSlot.vue'
import { ref } from 'vue'
let name = ref("dynamic1")
const changeSlot = () => {
name.value = "dynamic2"
}
</script>
4. 作用域插槽(子组件向父组件传值的一种方式)
子组件中
<template>
<div v-for="(item, index) in objs">
<!-- 给插槽绑定一些值,可以传到父组件 v-slot 标签中解构出来 -->
<slot :index="index" :data="item"></slot>
</div>
</template>
<script setup lang="ts">
import { reactive } from 'vue';
const objs = reactive([
{
name: 'zs',
age: 18
},
{
name: 'ls',
age: 19
},
{
name: 'ww',
age: 20
},
{
name: 'll',
age: 21
},
])
</script>
父组件中
<template>
<child-slot>
<!-- 将子组件插槽中绑定的值解构出来,就可以使用 -->
<template v-slot="{index, data}">
<div>
{{ index }} -- {{ data.name }} -- {{ data.age }}
</div>
</template>
</child-slot>
</template>