文章目录
- [1. 核心:通用动态插槽组件](#1. 核心:通用动态插槽组件)
- [2. 使用页面 1:表单卡片(最常用场景)](#2. 使用页面 1:表单卡片(最常用场景))
- [3. 使用页面 2:列表卡片(完全不同场景)](#3. 使用页面 2:列表卡片(完全不同场景))
- [✏️ 核心用法总结](#✏️ 核心用法总结)
- [🎯 这个组件的超级优势](#🎯 这个组件的超级优势)

这里封装一个开箱即用、任意页面都能复用 的 DynamicSlotBox 通用插槽组件。
特点:
- 支持任意插槽名称(配置驱动)
- 支持默认内容
- 支持作用域传参(子→父传数据)
- 支持循环批量渲染插槽
- 任意页面引入就能用,无需改组件内部代码
直接给你完整 3 个文件:
- 通用插槽组件(只写一次,到处复用)
- 使用页面示例 1
- 使用页面示例 2
1. 核心:通用动态插槽组件
components/DynamicSlotBox.vue
vue
<template>
<div class="dynamic-slot-box" :style="wrapperStyle">
<!-- 批量循环渲染插槽:根据传入的 slotNames 生成 -->
<div
class="slot-item"
v-for="slotName in slotNames"
:key="slotName"
:style="itemStyle"
>
<!-- 核心:动态具名插槽 + 作用域数据 -->
<slot :name="slotName" :slotData="scopeData">
<!-- 默认内容 -->
<div class="slot-default-tip">
插槽「{{ slotName }}」未填充内容
</div>
</slot>
</div>
</div>
</template>
<script setup>
import { computed } from 'vue'
// 父组件传入配置:插槽名称数组
const props = defineProps({
// 插槽名称列表,例如 ['header', 'body', 'footer', 'table']
slotNames: {
type: Array,
required: true,
default: () => []
},
// 可选:传给所有插槽的公共作用域数据
scopeData: {
type: Object,
default: () => ({})
},
// 外层样式
wrapperStyle: {
type: Object,
default: () => ({})
},
// 每个插槽项样式
itemStyle: {
type: Object,
default: () => ({})
}
})
</script>
<style scoped>
.dynamic-slot-box {
margin: 16px 0;
border: 1px solid #eee;
border-radius: 8px;
padding: 12px;
}
.slot-item {
margin: 8px 0;
padding: 12px;
min-height: 40px;
border: 1px dashed #ccc;
border-radius: 6px;
}
.slot-default-tip {
color: #999;
font-size: 13px;
}
</style>
2. 使用页面 1:表单卡片(最常用场景)
views/FormPage.vue
vue
<template>
<div>
<h2>表单页面(使用通用插槽组件)</h2>
<!-- 只需传入插槽名称数组,即可自动生成插槽 -->
<DynamicSlotBox
:slotNames="['formHeader', 'formBody', 'formFooter']"
:scopeData="{ formId: 10086, user: '张三' }"
>
<!-- 填充头部插槽 -->
<template #formHeader>
<h3>用户编辑表单</h3>
</template>
<!-- 填充表单体插槽 -->
<template #formBody>
<div>姓名:<input /></div>
<div>年龄:<input /></div>
</template>
<!-- 接收子组件传来的作用域数据 -->
<template #formFooter="scope">
<button>提交</button>
<p>表单ID:{{ scope.slotData.formId }}</p>
</template>
</DynamicSlotBox>
</div>
</template>
<script setup>
import DynamicSlotBox from '@/components/DynamicSlotBox.vue'
</script>
3. 使用页面 2:列表卡片(完全不同场景)
views/ListPage.vue
vue
<template>
<div>
<h2>列表页面(复用同一个插槽组件)</h2>
<DynamicSlotBox
:slotNames="['listTop', 'listTable', 'listPagination']"
:scopeData="{ total: 100 }"
>
<template #listTop>
<button>新增</button>
<button>批量删除</button>
</template>
<template #listTable>
<table border="1" cellpadding="10">
<tr><td>列表内容 1</td></tr>
<tr><td>列表内容 2</td></tr>
</table>
</template>
<template #listPagination="scope">
共 {{ scope.slotData.total }} 条
</template>
</DynamicSlotBox>
</div>
</template>
<script setup>
import DynamicSlotBox from '@/components/DynamicSlotBox.vue'
</script>
✏️ 核心用法总结
子组件(通用)
vue
<slot :name="slotName" :slotData="scopeData" />
父组件(使用)
vue
<DynamicSlotBox :slotNames="['A','B','C']">
<template #A> 内容A </template>
<template #B> 内容B </template>
<template #C> 内容C </template>
</DynamicSlotBox>
🎯 这个组件的超级优势
- 一次封装,全局复用
- 不修改组件代码,只需配置数组
- 支持任意业务:表单、列表、弹窗、步骤、卡片
- 支持作用域插槽,子传父数据
- 自带默认内容,不填插槽也不报错
- 支持动态样式