Vue3 通用可复用动态插槽组件(终极版)

文章目录

这里封装一个开箱即用、任意页面都能复用DynamicSlotBox 通用插槽组件

特点:

  • 支持任意插槽名称(配置驱动)
  • 支持默认内容
  • 支持作用域传参(子→父传数据)
  • 支持循环批量渲染插槽
  • 任意页面引入就能用,无需改组件内部代码

直接给你完整 3 个文件

  1. 通用插槽组件(只写一次,到处复用)
  2. 使用页面示例 1
  3. 使用页面示例 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>

🎯 这个组件的超级优势

  1. 一次封装,全局复用
  2. 不修改组件代码,只需配置数组
  3. 支持任意业务:表单、列表、弹窗、步骤、卡片
  4. 支持作用域插槽,子传父数据
  5. 自带默认内容,不填插槽也不报错
  6. 支持动态样式

相关推荐
赵庆明老师17 分钟前
Vben精讲:16-熟悉Vite前端工具链
前端
瑞瑞小同学2 小时前
处理echarts x轴内容过多,重叠问题
前端·javascript·echarts
HexCIer3 小时前
面向未来的原子化 CSS:UnoCSS 核心架构分析与 Tailwind CSS 现状
前端·css·vite
程序员黑豆3 小时前
鸿蒙应用开发中的单位详解:px、vp、fp、lpx
前端·harmonyos
像我这样帅的人丶你还3 小时前
MCP + npm:给五年前的老系统接上AI
前端·javascript·agent
南一Nanyi3 小时前
依赖注入和控制反转
前端·设计模式·nestjs
小村儿3 小时前
连载14-实战篇--一个半月,我一个人和 Claude Code 搭出一套数字人工程
前端·后端·ai编程
愚公移码4 小时前
蓝凌EKP18产品:流程虚拟机(PVM)
java·开发语言·前端
promiseThen4 小时前
5 分钟上手 Markdown:标题到表格、代码块与简历实战
前端
web66liang4 小时前
webpack4+vue2项目使用 sass-embedded 导致的 DockerfIle 构建失败的问题
前端