阅读视图

发现新文章,点击刷新页面。

里程碑4 - 基于Vue3完成动态组件库建设

一、目标

在之前的过程中,基于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...]
❌