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. 支持动态样式

相关推荐
lichenyang4531 天前
Docker 学习笔记(一):为什么需要镜像、容器和仓库?
前端
kyriewen1 天前
别再对着 TypeScript 报错发呆了:我把 10 个最常见的红色波浪线翻译成了人话
前端·javascript·typescript
IT_陈寒1 天前
SpringBoot自动配置的坑,我的API突然就404了
前端·人工智能·后端
free351 天前
从 0 实现一个 Tiny JavaScript VM:项目架构拆解
javascript
暴走的小呆1 天前
Vue 2 中 Object 的变化侦测:从 getter/setter 到 Dep、Watcher、Observer
vue.js
奇奇怪怪的1 天前
Embedding 模型 10+ 横向评测
前端
陈广亮1 天前
Monorepo 从 0 到 1 实操指南 2026 版:pnpm catalogs + Turborepo 2.x + changesets 全链路
前端
子兮曰1 天前
OpenMontage 深度解剖:你的 AI 编程助手,其实是个视频工作室
前端·后端·ai编程
敲代码的鱼1 天前
PDF 预览与签名批注写回 支持安卓 iOS 鸿蒙 UTS插件
android·前端·ios