【Vue3】如何使用插槽

默认插槽

插槽可以让父组件给子组件传递模板片段

  1. 在父组件中,在组件内编写模板片段传递给子组件
  2. 在子组件中,编写 slot 元素,指定模板片段输出的位置
  • 插槽内容可以访问到父组件的数据,但无法访问到子组件的数据。因为插槽本身是在父组件模板中定义的
  • 可以在子组件的 slot 标签内设置插槽的默认内容。当父组件没有提供任何插槽内容时,子组件会渲染默认内容
<template>
    <!-- 在组件内编写模板片段传递给子组件 -->
    <HelloWorld> {
   
   { content }} </HelloWorld>
</template>

<script lang="ts" setup>
import HelloWorld from '@/components/HelloWorld.vue';
import {
      
       ref } from 'vue';

const content = ref('插槽内容');
</script>
<template>
    <p>
        <!-- 编写 `slot` 元素,指定模板片段输出的位置 -->
        <slot> 插槽默认内容 </slot>
    </p>
</template>



具名插槽

当一个组件中包含多个插槽出口时,需使用具名插槽指定父组件中的内容要传到哪个 slot 元素内

  1. 在子组件中,给 slot 元素设置 name attribute,来唯一标识各个插槽

    没有提供 nameslot 会隐式地命名为 'default'

  2. 在父组件中,给 template 元素设置 v-slot 指令,并将目标插槽的名字传给该指令

    v-slot 指令可以简写为 #

    • 默认插槽写法:v-slot / v-slot:default / #default
    • 具名插槽写法:v-slot:XXName / #XXName
<template>
    <p>
        <slot name="header"> header 插槽默认内容 </slot>
        <slot> 插槽默认内容 </slot>
        <slot name="footer"> footer 插槽默认内容 </slot>
    </p>
</template>
<template>
    <HelloWorld>
        <template #header> header </template>
        <template #default> default </template>
        <template #footer> footer </template>
    </HelloWorld>
</template>

<script lang="ts" setup>
import HelloWorld from '@/components/HelloWorld.vue';
</script>
  • 当一个组件同时接收默认插槽和具名插槽时,所有位于顶级的非 template 节点都被隐式地视为默认插槽内容。
    所以上例可以写成:
<template>
    <HelloWorld>
        <template #header> header </template>
        <!-- 隐式的默认插槽 -->
        default
        <template #footer> footer </template>
    </HelloWorld>
</template>



作用域插槽

在某些场景下,插槽的内容需要使用到子组件中的数据。此时可以使用作用域插槽

  1. 在子组件中,给 slot 元素设置自定义属性,以传递数据给父组件
  2. 在父组件中,从 v-slot 指令的值中获取子组件传递过来的数据
    • 默认插槽写法:v-slot="XXX" / v-slot:default="XXX" / #default="XXX"
    • 具名插槽写法:v-slot:XXName="XXX" / #XXName="XXX"
  • 注意插槽上的 name 是一个 Vue 特别保留的 attribute,不会作为 props 传递给插槽
<template>
    <p>
        <slot
            name="header"
            text="header slot"
        >
            header 插槽默认内容
        </slot>
        <!-- 使用 v-bind 设置自定义属性 -->
        <slot v-bind="data"> 插槽默认内容 </slot>
    </p>
</template>

<script setup lang="ts">
import {
      
       ref } from 'vue';

const data = ref({
      
       text: 'default slot', number: 1 });
</script>
<template>
    <HelloWorld>
        <template #header="headerData"> header: {
   
   { headerData }} </template>
        <!-- 使用 [解构赋值] 获取子组件传递过来的数据 -->
        <template #default="{ text, number }"> default: {
   
   { text }} - {
   
   { number }}</template>
    </HelloWorld>
</template>

<script lang="ts" setup>
import HelloWorld from '@/components/HelloWorld.vue';
</script>



动态插槽名

可以给 v-slot 指令传递动态参数,就可以定义动态插槽名啦

  • 动态参数中表达式的值只能为 String / nullnull 表示移除该绑定
  • 动态参数表达式有一些语法限制,比如空格和引号,在 HTML attribute 名称中都是不合法的;
    推荐使用 [计算属性] 替换复杂的表达式
<base-layout>
  <template v-slot:[dynamicSlotName]>
    ...
  </template>

  <!-- 缩写为 -->
  <template #[dynamicSlotName]>
    ...
  </template>
</base-layout>



猜你喜欢

转载自blog.csdn.net/Superman_H/article/details/128846817