vue3(七)slot插槽

224 阅读1分钟

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>