插槽
基本使用
<slot>
元素就是一个 插槽出口,标识了父元素提供的 插槽内容 在哪里渲染。
vue
<template>
<HelloWorld> Click Me </HelloWorld>
</template>
<script setup lang="ts">
import HelloWorld from "./components/HelloWorld.vue"
</script>
vue
<template>
<button @click="handleClick">
<!-- 这是插槽的默认内容 -->
<slot>click me</slot>
</button>
</template>
具名插槽
具名插槽可以在 <slot>
中使用 name
属性指定,没有提供 name
属性或使用 #default
的插槽叫默认插槽。
vue
<template>
<HelloWorld>
<template #header>header头部插槽内容</template>
<template #default>default默认插槽内容</template>
<template #footer>footer尾部插槽内容</template>
</HelloWorld>
</template>
<script setup lang="ts">
import HelloWorld from "./components/HelloWorld.vue"
</script>
vue
<template>
<div id="container">
<header>
<slot name="header"></slot>
</header>
<main>
<!-- 默认插槽,不写name默认会识别为default -->
<!-- <slot></slot> -->
<slot name="default"></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
</template>
动态插槽
动态指令参数 在 v-slot
上也是有效的,即可以定义下面这样的动态插槽名:
vue
<template>
<HelloWorld>
<template #[dynamicSlotName]>header头部插槽内容</template>
<template #default>default默认插槽内容</template>
<template #[dynamicSlotName]>footer尾部插槽内容</template>
</HelloWorld>
</template>
<script setup lang="ts">
import { ref } from "vue"
import HelloWorld from "./components/HelloWorld.vue"
const dynamicSlotName = ref("header")
setTimeout(() => {
// 默认显示 header 插槽,3秒后显示 footer 插槽
dynamicSlotName.value = "footer"
}, 3000)
</script>
vue
<template>
<div id="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot name="default"></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
</template>
作用域插槽
在某些场景下,如果子组件的数据想要通过插槽传递给父组件,那么就可以使用作用域插槽。
vue
<template>
<HelloWorld>
<template #header="slotProps">
<div>{{ slotProps.message }}</div>
</template>
<!-- 使用解构的语法 -->
<template #default="{ count }">
<div>{{ count }}</div>
</template>
</HelloWorld>
</template>
<script setup lang="ts">
import HelloWorld from "./components/HelloWorld.vue"
</script>
vue
<template>
<div id="container">
<header>
<slot name="header" :message="message"></slot>
</header>
<main>
<slot name="default" :count="count"></slot>
</main>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue"
const message = ref("hello,world")
const count = ref(100)
</script>
注意
在作用插槽中,name
属性是一个关键字,插槽中使用 name 传递的属性,父组件接收不到。
vue
<!-- name属性接收不到,而 message 可以 -->
<slot name="tom" message="hello"></slot>