slot 插槽
插槽内容可以是任意合法的模板内容,不局限于文本。例如我们可以传入多个元素,甚至是组件。
匿名插槽
父组件:
<template>
<child>
我是父组件 <!-- 插槽内容 -->
</child>
</template>
<script setup lang="ts">
import child from '../components/child.vue';
</script>
子组件:
<template>
<div class="child">
<slot></slot> <!-- 插槽出口 -->
</div>
</template>
具名插槽
一个组件中可以有多个插槽出口,使用具名插槽确定出口所在位置
父组件:v-slot="插槽名称",也可以使用简写:#名称
<template>
<child>
<template v-slot:slotHeader>我是父组件header</template>
<template v-slot:slotFooter>我是父组件footer</template>
<!-- 简写为 -->
<template #slotHeader>我是父组件header</template>
<template #slotFooter>我是父组件footer</template>
</child>
</template>
子组件:使用 name="插槽名称",确定插槽位置
<template>
<div class="child">
<div class="header">
<slot name="slotHeader"></slot>
</div>
<div class="footer">
<slot name="slotFooter"></slot>
</div>
</div>
</template>
动态插槽名
插槽名称也可以是动态的,语法: v-slot:[插槽名],简写 #[插槽名]
<template>
<child>
<template v-slot:[slotHeader]>我是父组件header</template>
<template v-slot:[slotFooter]>我是父组件footer</template>
<!-- 简写 -->
<template #[slotHeader]>我是父组件header</template>
<template #[slotFooter]>我是父组件footer</template>
</child>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import child from '../components/child.vue';
const slotHeader = ref('slotHeader')
const slotFooter = ref('slotFooter')
</script>
作用域插槽
在上面的内容中,插槽的内容是无法访问到子组件的
如果需要使用到子组件中的数据,可以使用作用域插槽,子组件在渲染时将一部分数据提供给插槽。
作用域插槽:匿名插槽写法
父组件: 通过子组件标签上的 v-slot 指令,接收到了一个插槽 props
<template>
<child v-slot="slotProps">
{{ slotProps }}
<hr>
{{ slotProps.text }}
</child>
</template>
<!-- 也可以通过解构的方式获取值 -->
<child v-slot="{ text }">
{{ text }}
</child>
子组件:可以像对组件传递 props 那样,向一个插槽的出口上传递 attributes:
<template>
<div class="child">
<slot :text="childText"></slot>
</div>
</template>
<script setup lang='ts'>
import { ref } from 'vue'
const childText = ref("子组件内容")
</script>
作用域插槽:具名插槽写法
父组件
<template>
<child>
<template #header="headerProps">
{{ headerProps }}
</template>
<template #footer="footerProps">
{{ footerProps }}
</template>
</child>
</template>
子组件:注意插槽上的 name 是一个 Vue 特别保留的 attribute,不会作为 props 传递给插槽。
因此最终 headerProps 的结果是 { text: '我是header' }。
<template>
<div class="child">
<slot name="header" text="我是header"></slot>
<slot name="footer" text="我是footer"></slot>
</div>
</template>