vue3 插槽使用

213 阅读2分钟

Vue3插槽的使用方式与Vue2类似,但结合组合式API后有了更灵活的实现。以下是核心用法及示例:

一、默认插槽

在子组件中通过 <slot></slot> 定义默认插槽,父组件通过标签包裹内容插入:

<!-- 子组件 Child.vue -->
<div>
  <slot>默认内容(当父组件未传内容时显示)</slot>
</div>

<!-- 父组件使用 -->
<Child>
  <p>自定义内容</p>
</Child>

二、具名插槽

通过 name 属性定义多个插槽区域:

<!-- 子组件 -->
<div>
  <slot name="header"></slot>
  <slot name="content"></slot>
</div>

父组件通过 <slot> 标签指定名称插入:

<Child>
  <template #header>
    <h1>标题</h1>
  </template>
  <template #content>
    <p>正文内容</p>
  </template>
</Child>

三、作用域插槽(动态数据传递)

子组件通过 $emitv-slot 传递数据给父组件插槽:

<!-- 子组件 -->
<div>
  <slot name="item" :user="user"></slot>
</div>

父组件接收数据:

<Child>
  <template #item="{ user }">
    <div>{{ user.name }} - {{ user.age }}</div>
  </template>
</Child>

四、动态插槽

结合 v-if/v-for 动态控制插槽内容:

<Child>
  <template v-if="showHeader" #header>
    <h1>动态标题</h1>
  </template>
</Child>

五、组合式API中的插槽处理

  • setup() 中通过 defineSlots() 显式声明插槽结构,主要用于在<script setup>语法中为组件的插槽提供类型定义,能让ts在父组件中使用插槽时提供类型提示和校验。

  • defineSlots()纯粹是为了类型检查而存在的,编译后的代码中,这个函数会被移除,所以不会增加运行时的开销

使用示例:

//子组件
<script setup lang="ts">  
// 子组件:声明插槽类型  
const slots = defineSlots<{  
default: (props: { id: number; text: string }) => any; //any不是强制要求,只是占位符表示允许返回任何值;核心类型安全在于作用域参数的定义,而非返回值类型 
title?: () => any; // 可选的具名插槽  
}>();  
</script>

<template>
<!-- 使用插槽 -->  
<slot :id="1" text="Hello" />  
<slot name="title" />  
</template>
//在父组件中使用时,ts会检查作用域参数的类型:
<template>  
    <Child>  
    <!-- 作用域参数 `id` 和 `text` 的类型会被自动推断 -->  
    <template #default="{ id, text }">{{ id }} - {{ text }}</template>  
    <template #title>标题</template>  
    </Child>  
</template>

总结

Vue3插槽的核心逻辑与Vue2保持一致,但通过组合式API增强了类型安全和代码组织能力。