Vue3 插槽完整实战(具名插槽 + 动态插槽),以下会给你可直接运行的完整代码 ,包含父组件 + 子组件,实现:
- 基础具名插槽
- 灵活的动态插槽(根据名称自动匹配渲染)
- 作用域插槽(子传数据给父)

1. 子组件:SlotChild.vue(插槽容器)
这个组件定义多个具名插槽 + 动态插槽出口,提供默认内容。
vue
<template>
<div class="child-box">
<h3>子组件(插槽容器)</h3>
<!-- 1. 固定具名插槽:头部 -->
<div class="slot-header">
<slot name="header">
<!-- 插槽默认内容:父组件不传时显示 -->
<p>默认头部</p>
</slot>
</div>
<!-- 2. 核心:动态插槽(根据名称灵活渲染) -->
<div class="slot-dynamic" v-for="name in dynamicSlotNames" :key="name">
<slot :name="name">默认 {{ name }} 区域内容</slot>
</div>
<!-- 3. 作用域插槽:子组件把数据传给父组件 -->
<div class="slot-scope">
<slot name="scope" :user="userInfo" :msg="scopeMsg">
默认作用域插槽
</slot>
</div>
<!-- 4. 匿名插槽(默认插槽) -->
<div class="slot-default">
<slot>默认匿名插槽</slot>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
// 动态插槽名称列表 → 父组件可以灵活匹配
const dynamicSlotNames = ref(['top', 'center', 'bottom'])
// 作用域插槽要传递的数据
const userInfo = ref({ name: 'Vue新手', age: 20 })
const scopeMsg = ref('这是子组件传给父的消息')
</script>
<style scoped>
.child-box {
border: 2px solid #42b983;
padding: 20px;
margin: 20px 0;
border-radius: 8px;
}
.slot-header, .slot-dynamic, .slot-scope, .slot-default {
margin: 10px 0;
padding: 10px;
border: 1px dashed #666;
}
</style>
子组件核心说明
name="header":固定具名插槽v-for+:name="name":动态插槽(父组件想传几个就匹配几个):user="userInfo":作用域插槽(子 → 父传数据)- 不带 name 的
<slot>:匿名默认插槽
2. 父组件:SlotParent.vue(使用插槽)
父组件通过 v-slot:名称(简写 #名称)匹配子组件插槽,支持动态名称。
vue
<template>
<div class="parent-box">
<h2>父组件(使用插槽)</h2>
<SlotChild>
<!-- 1. 匹配固定具名插槽:header -->
<template #header>
<h4 style="color: #2f4050;">✅ 父组件传入:头部插槽内容</h4>
</template>
<!-- 2. 动态匹配插槽:对应子组件 dynamicSlotNames -->
<template #top>
<span style="color: #409eff;">动态 top 区域</span>
</template>
<template #center>
<span style="color: #e6a23c;">动态 center 区域</span>
</template>
<template #bottom>
<span style="color: #67c23a;">动态 bottom 区域</span>
</template>
<!-- 3. 作用域插槽:接收子组件传过来的数据 -->
<template #scope="scopeData">
<div>
<p>接收子数据:{{ scopeData.user.name }},年龄:{{ scopeData.user.age }}</p>
<p>子消息:{{ scopeData.msg }}</p>
</div>
</template>
<!-- 4. 匿名默认插槽 -->
<div>✅ 父组件传入:默认匿名插槽内容</div>
</SlotChild>
</div>
</template>
<script setup>
// 引入子组件
import SlotChild from './SlotChild.vue'
</script>
<style scoped>
.parent-box {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
</style>
3. 最灵活方案:动态插槽名(进阶)
如果你想要完全根据变量自动渲染插槽 ,用动态指令:
vue
<template>
<SlotChild>
<!-- 变量控制插槽名称,实现 100% 动态 -->
<template #[dynamicSlotName]>
动态名称插槽内容
</template>
</SlotChild>
</template>
<script setup>
import SlotChild from './SlotChild.vue'
import { ref } from 'vue'
// 插槽名可以从接口、配置、循环中动态获取
const dynamicSlotName = ref('center')
</script>
#[dynamicSlotName] = 动态绑定插槽名称,配置化、极高灵活性。
4. 核心知识点总结
-
具名插槽
- 子:
<slot name="xxx"> - 父:
<template #xxx>
- 子:
-
动态插槽(最实用)
- 子:循环生成
<slot :name="item"> - 父:用对应名称匹配
- 超级灵活:适合表单、弹窗、列表、卡片等可复用组件
- 子:循环生成
-
作用域插槽
- 子:
<slot :数据名="值"> - 父:
<template #xxx="接收对象">
- 子:
-
简写规则
v-slot:header简写为#header
总结
- 你可以直接复制这两个文件运行
- 子组件负责定义插槽出口
- 父组件负责填充内容
- 动态插槽让组件高度复用、可配置、可扩展
- 作用域插槽解决子组件数据传给父插槽使用的场景