Skip to content

插槽

基本使用

<slot> 元素就是一个 插槽出口,标识了父元素提供的 插槽内容 在哪里渲染。

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>

Released under the MIT License.