里程碑4 - 基于Vue3完成动态组件库建设
2026年3月12日 18:15
一、目标
在之前的过程中,基于DSL完成了列表页面的领域模型搭建和页面的动态开发,接下来我们是要根据列表页展示的按钮,完成详情的 动态增改查 功能
二、配置项展示
1. xxxOption(字段级配置)
这部分设置的是某个字段在某个页面中的表现方式,用来控制每个字段如何渲染,比如是要隐藏或是禁用。
其中新增、修改页面的控件类型comType是必须要进行配置的,用于后续数据填写;而查看详情页面可以添加控件组件comType,和新增、修改采用同一种样式展示、也可以不配置控件组件,自定义展示样式。
以下是代码用例:
xxxPageOption: {
...elComponentConfig, // 标准 el-component配置
comType: "", // 控件类型 input/select/input-number
visible: true, // 是否展示,默认为true
disabled: false, // 是否禁用,默认为false
default: "", // 默认值
enumList: [], // 枚举列表,comType === select时生效
},
2. componentConfig(组件级配置)
这部分配置是用来控制页面的行为;根据之前按钮配置的eventKey和eventOption中的comName来决定展示哪个页面
适合用来控制一些页面属性
// 动态组件 相关配置
componentConfig: {
xxxPage: {
title: '', // 表单标题
saveBtnText: '', // 保存按钮文案
mainKey: '', // 表单主键,用于唯一标识要修改的数据对象,修改和查看必须进行配置
},
// ... 支持用户动态扩展
}
3. 两者之间的结构关系
Schema
├─ properties (字段级)
│ ├─ field1
│ │ ├─ xxxPageOneOption
│ │ ├─ xxxPageTwoOption
│ │ └─ xxxPageThreeOption
│ └─ field2
│
componentConfig (页面级)
├─ xxxPageOne
├─ xxxPageTwo
└─ xxxPageThree
三、与代码配置页面的比对
| 代码配置页面 | DSL领域模型生成 | |
|---|---|---|
| 开发方式 | 写代码 | 写配置 |
| 页面数量 | 一个页面一套代码 | 一个组件根据配置可以生成多个页面 |
| 样式风格 | 难以统一 | 容易保持一致 |
-
DSL的核心优势
一个schema可以生成,达到页面生成自动化,且UI样式统一,降低重复代码
四、最终DSL架构
经过不断的完善和扩展,我们最终的DSL架构样式为:
schema: {
properties: {
key: {
...schema,
label: '',
type: '',
searchOption: {
},
tableOption: {
},
xxxPageOneOption: {
},
xxxPageTwoOption: {
},
}
},
required: ["key"],
}
searchConfig: {},
tableConfig: {},
component: {
xxxPageOne: {
},
xxxPageTwo: {
},
},
五、总结
为解决前端代码开发过程中遇到的 页面重复度高、大量CRUD页面结构相似,每个页面独立完成导致的后续高维护成本和扩展困难等问题,我们从手写每个页面代码 转变为 使用DSL配置描述页面结构。
在开发过程中,通过领域模型model和衍生出的各类project配置,结合统一的schema配置描述页面结构,动态生成页面。从而达到将重复代码沉淀下来,让我们有更多的精力去完成定制化需求。
六、开发过程中遇到的😅事情
vue动态组件 + ref 收集方式
-
修改前的写法
<component v-for='item in List" :ref="handleSearchComList"/> const searchComList = ref([]); const handleSearchComList = (el) => { searchComList.value.push(el); } -
错误的修改
<component v-for="item in list" :ref="searchComList"/> const searchComList = ref([]);因为我定义的是 searchComList = ref([]),vue会认为这是一个ref对象,然后尝试
searchComList.value = el;这样会导致 过程中每次ref都会覆盖,不会push,所以在我打印的时候看到的是空的 -
正确的修改
<component v-for="item in list" ref="searchComList"/> const searchComList = ref([]); -
情况比对
写法 是否可用 原因 :ref="schemaComList" 不可用 :ref="XXX"动态ref,是js表达式绑定,vue会理解为 XXX.value = el,会被覆盖,在最后组件更新或卸载的时候,打印出来的结果就是空数组或者null :ref="handleSearchComList" + handleSearchComList() 可用 定义的handleSearchComList是函数,vue会执行这段函数,会在函数中进行push ref="searchComList" + v-for 可用 ref="XXX" 静态ref,XXX只是一个字符串key,vue会在挂载后自动做 XXX.value = 组件实例;如果是v-for,vue会自动收集 XXX.value = [实例1,实例2...]