基于领域模型的动态组件扩展设计

101 阅读4分钟

本文围绕上一篇 基于 DSL 与领域模型的系统构建方案 5.2 中的组件拓展 描述动态组件拓展的具体实现。

动态组件的实现机制是一套通过配置+ 数据驱动 + 事件驱动来实现组件动态加载、渲染及交互的完整体系,其核心在于通过标准化的配置格式和灵活的事件机制,降低组件开发的重复工作,提升系统的可扩展性和可维护性。以下是对该机制的详细理解:

一、动态组件的核心设计理念

1. 配置驱动渲染

通过统一的配置文件(如 componentConfig)定义组件的结构、属性和行为,避免硬编码。例如,表单组件可通过 schema 解析数据并渲染表单项,实现 “一份数据渲染多种表单”(如搜索栏、新增 / 修改表单)。

2. 事件驱动交互

组件间通过事件通信,如点击按钮时抛出事件,由 schema-view 接收并触发对应组件的展示或数据更新。例如,“新增” 按钮抛出事件后,schema-view 调用表单组件并在提交后通知列表组件刷新数据。

3. 数据驱动开发

以数据为核心驱动组件逻辑,避免逻辑混乱。例如,从 dashboard 的 hook 开始处理数据,通过 Model 和 Schema 控制表单值和渲染结构。

二、动态组件的实现流程与机制

以新增表单组件create-form为例说明:

1. 组件配置与解析

  • 配置目标: 通过组件配置和解析器,支持表单组件的动态生成。

  • 配置结构

schemaConfig: {
    schema: {
        type: 'object',
        properties: { 
          product_name: {
            ...
            createFormOption: {
              comType: 'input',
              default: '新课程'
            }       
          },
          price: {
            createFormOption: {
              comType: 'inputNumber'
            }
          },
          inventory: {
            ...
            createFormOption: {
              comType: 'select',
              enumList: [
                {label: '100', value: 100},
                {label: '1000', value: 1000},
                {label: '10000', value: 10000}
              ]
            }
          }
        },
        required: ['product_name']  // 表单必填字段
      },
      componentConfig: {
        createForm: {
          title: '新增商品',
          saveBtnText: '保存商品'
        },
        ...
      }
}

(1)componentConfig:用于配置所有的动态组件(如 createForm、componentA、componentB...),组件所拥有的字段(title、saveBtnText...)支持用户动态拓展;

(2)componentSchemaOption:createFormOption 用于解析数据渲染表单项,例如表单的字段类型、是否必填、默认值等,兼容 Element UI 原生属性。

  • 配置解析
// 取出 componentConfig
const { componentConfig } = schemaConfig;

// 构造动态组件数据
if(componentConfig && Object.keys(componentConfig).length > 0){
  const dtoComponents = {};
  for(const comName in componentConfig){
    dtoComponents[comName] = {
      schema: buildDtoSchema(configSchema, comName),
      config: componentConfig[comName]
    };
  }
  components.value = dtoComponents;
}

// 最终得到的数据结构为:
// components = { 
//  comA : { schema, config },
//  comB : { schema, config },
// }

通过 schema(决定组件结构、组件内字段呈现方式)和 config(决定组件相关值)驱动渲染;

2. 组件加载机制

  • 组件创建与管理

image.png 新建components目录,用于存放各动态组件,如create-form、edit-form....,并将动态组件统一配置在 component-config.js 中。

  • 事件触发加载

    动态组件需通过事件触发,而非直接展示(区别于搜索栏和表格的字段配置直接渲染)。


<template>
  <el-row class="schema-view">
    ...
    <table-panel ref="tablePanelRef" @operate="onTableOperate"></table-panel>

    <component 
      :is="ComponentConfig[key]?.component"
      v-for="(item,key) in components"
      :key="key"
      ref="comListRef"
      @command="onComponentCommand"
    ></component>
  </el-row>
</template>

...
import ComponentConfig from './components/component-config.js';
import { useSchema } from './hook/schema.js';
const { 
  api, 
  ...
  components
} = useSchema();

// table事件触发
const onTableOperate = ({btnConfig, rowData})=>{
  const { eventKey } = btnConfig;
  if(EventHandleMap[eventKey]){
    EventHandleMap[eventKey]({btnConfig, rowData});
  }
};

// table事件映射
const EventHandleMap = {
  showComponent: showComponent
};

// 展示动态组件
function showComponent({ btnConfig, rowData }){
  const { comName } = btnConfig.eventOption;
  if(!comName) {
    console.log('没配置组件名');
    return;
  };
  
  const comRef = comListRef.value.find(item=>item.name === comName);
  if(!comRef || typeof comRef.show !== 'function') {
    console.log(`找不到组件:${comName}`);
    return;
  };

  comRef.show(rowData);
};

核心逻辑:

(1)从 hook/schema.js 获取 API 和 components 配置,通过 provide/inject 实现组件间数据交互;

(2)通过 table-panel 组件的 onTableOperate 事件触发EventHandleMap 事件映射配合实现动态组件的渲染。

3. 事件映射与通信

  • 事件驱动流程:

    (1)按钮(如表格头部按钮、侧边栏按钮)配置事件(如 removeshowComponent);

    (2)schema-view 接收事件并根据 eventKey 调用对应方法。 如showComponent 事件触发时,从 eventOption 获取组件名称,调用其 show 方法并传入数据rowData。

  • 组件间协作:

    schema 与组件通过 “桥梁”(如 search-paneltable-panel)连接,组件完成操作后返回事件通知其他组件(如列表刷新)。

三、动态组件的优势

  • 优势

    • 减少重复开发:通过配置沉淀 80% 的重复工作,如表单渲染、事件处理逻辑;
    • 灵活扩展:支持无限拓展组件(如增删改查、详情查看等),适配不同业务场景。

四、总结

动态组件的实现机制通过 “配置 + 事件 + 数据” 的设计,实现了组件的动态化、标准化和可扩展化,实现了改一改配置、调一调数据就能快速适配各业务场景,为复杂业务的前端开发提供了高效的解决方案。

引用:抖音“哲玄前端”,《全栈实践课》