vue2 和 vue3 中,插槽、具名插槽、插槽传参用法

在 Vue 2 和 Vue 3 中,插槽(Slot)是组件间传递内容的重要机制,用于实现组件的灵活复用。两者在插槽的基本概念上一致,但在语法细节、具名插槽用法、作用域插槽(插槽传参)的写法上存在明显差异。

一、默认插槽(匿名插槽)

默认插槽是最基础的插槽,用于传递无名称的内容。

Vue 2 用法:
  • 子组件中用 <slot></slot> 定义插槽出口
  • 父组件中直接在子组件标签内写入内容,会被分发到默认插槽
vue 复制代码
<!-- 子组件 Child.vue -->
<template>
  <div class="child">
    <h3>子组件标题</h3>
    <slot></slot>
    <!-- 插槽出口 -->
  </div>
</template>

<!-- 父组件 Parent.vue -->
<template>
  <div class="parent">
    <Child>
      <!-- 插槽内容会被插入到子组件的 slot 位置 -->
      <p>这是默认插槽的内容</p>
    </Child>
  </div>
</template>
Vue 3 用法:

基本用法与 Vue 2 一致,但 Vue 3 对插槽的解析更严格,推荐显式使用 <template> 包裹(非必须)。

vue 复制代码
<!-- 子组件 Child.vue -->
<template>
  <div class="child">
    <h3>子组件标题</h3>
    <slot></slot>
    <!-- 插槽出口 -->
  </div>
</template>

<!-- 父组件 Parent.vue -->
<template>
  <div class="parent">
    <Child>
      <!-- 内容直接放入,或用 template 包裹 -->
      <template>
        <p>这是 Vue 3 默认插槽的内容</p>
      </template>
    </Child>
  </div>
</template>

二、具名插槽(Named Slots)

当组件需要多个插槽时,用名称区分不同插槽,称为具名插槽。

Vue 2 用法:
  • 子组件中用 name 属性定义具名插槽:<slot name="header"></slot>
  • 父组件中用 slot 属性指定内容对应的插槽名称:<p slot="header">...</p>
vue 复制代码
<!-- 子组件 Child.vue -->
<template>
  <div class="child">
    <slot name="header"></slot>
    <!-- 头部插槽 -->
    <slot></slot>
    <!-- 默认插槽(name 默认为 "default") -->
    <slot name="footer"></slot>
    <!-- 底部插槽 -->
  </div>
</template>

<!-- 父组件 Parent.vue -->
<template>
  <Child>
    <!-- 用 slot 属性指定插槽名称 -->
    <h1 slot="header">这是头部内容</h1>
    <p>这是默认插槽内容</p>
    <p slot="footer">这是底部内容</p>
  </Child>
</template>
Vue 3 用法:
  • 子组件定义方式不变:<slot name="header"></slot>
  • 父组件中必须用 <template> 配合 v-slot 指令 ,格式为 v-slot:插槽名(可简写为 #插槽名
vue 复制代码
<!-- 子组件 Child.vue -->
<template>
  <div class="child">
    <slot name="header"></slot>
    <slot></slot>
    <slot name="footer"></slot>
  </div>
</template>

<!-- 父组件 Parent.vue -->
<template>
  <Child>
    <!-- 具名插槽:v-slot:header 可简写为 #header -->
    <template #header>
      <h1>这是头部内容</h1>
    </template>

    <!-- 默认插槽:v-slot:default 可简写为 #default 或省略 -->
    <template #default>
      <p>这是默认插槽内容</p>
    </template>

    <template #footer>
      <p>这是底部内容</p>
    </template>
  </Child>
</template>

Vue 3 变化核心 :废弃 slot 属性,统一用 v-slot 指令,且必须配合 <template> 使用(默认插槽可省略 <template>,直接写内容)。

三、作用域插槽(插槽传参)

子组件向父组件的插槽内容传递数据(子传父),称为作用域插槽(即插槽传参)。

Vue 2 用法:
  • 子组件中通过 slot-scope 属性绑定数据:<slot :user="user" :age="18"></slot>
  • 父组件中用 slot-scope 接收数据(可在标签或 <template> 上)
vue 复制代码
<!-- 子组件 Child.vue -->
<template>
  <div class="child">
    <!-- 向插槽传递数据:user 和 age -->
    <slot name="content" :user="user" :age="18"></slot>
  </div>
</template>

<script>
export default {
  data() {
    return {
      user: { name: "张三", gender: "男" },
    };
  },
};
</script>

<!-- 父组件 Parent.vue -->
<template>
  <Child>
    <!-- 用 slot-scope 接收子组件传递的数据(对象形式) -->
    <template slot="content" slot-scope="slotProps">
      <p>姓名:{{ slotProps.user.name }}</p>
      <p>年龄:{{ slotProps.age }}</p>
    </template>
  </Child>
</template>
  • slotProps 是接收数据的变量名(可自定义),包含子组件传递的所有数据
  • 也可直接解构:slot-scope="{ user, age }"
Vue 3 用法:
  • 子组件传递数据的方式不变:<slot :user="user" :age="18"></slot>
  • 父组件中用 v-slot:插槽名="接收变量" 接收(可简写为 #插槽名="接收变量"
vue 复制代码
<!-- 子组件 Child.vue -->
<template>
  <div class="child">
    <slot name="content" :user="user" :age="18"></slot>
  </div>
</template>

<script setup>
import { reactive } from "vue";
const user = reactive({ name: "张三", gender: "男" });
</script>

<!-- 父组件 Parent.vue -->
<template>
  <Child>
    <!-- 用 #content="slotProps" 接收数据 -->
    <template #content="slotProps">
      <p>姓名:{{ slotProps.user.name }}</p>
      <p>年龄:{{ slotProps.age }}</p>
    </template>

    <!-- 也可直接解构 -->
    <template #content="{ user, age }">
      <p>姓名:{{ user.name }}</p>
      <p>年龄:{{ age }}</p>
    </template>
  </Child>
</template>

Vue 3 变化核心 :废弃 slot-scope 属性,统一用 v-slot 指令接收数据,写法更统一。

总结:Vue 2 vs Vue 3 插槽用法区别

类型 Vue 2 语法 Vue 3 语法 核心变化
具名插槽 slot="名称" 属性 <template v-slot:名称>#名称 废弃 slot 属性,改用 v-slot
作用域插槽 slot-scope 接收数据 v-slot:名称="变量" 接收数据 废弃 slot-scope,合并到 v-slot
默认插槽 直接写内容或 slot="default" 直接写内容或 #default 语法更简洁,推荐显式 <template>

注意 :Vue 3 对插槽语法做了标准化,更强调结构化和一致性,同时保持了核心功能不变。迁移时需注意将 slot 属性和 slot-scope 替换为 v-slot 指令。