lowcode-engine 设置器 API(Setters)完全指南:注册、管理自定义 Setter 与物料配置实战
2026/9/14 17:20:11 网站建设 项目流程

lowcode-engine 设置器 API(Setters)完全指南:注册、管理自定义 Setter 与物料配置实战

【免费下载链接】lowcode-engineAn enterprise-class low-code technology stack with scale-out design / 一套面向扩展设计的企业级低代码技术体系项目地址: https://gitcode.com/GitHub_Trending/lo/lowcode-engine

导读

本文围绕 lowcode-engine 的setters设置器 API 展开,讲解如何注册、获取与管理设置器,以及如何将自定义 Setter 接入物料协议,让属性面板真正驱动组件配置。读完本文,你将掌握getSettergetSettersMapregisterSetter三个核心方法的使用方式,能够独立开发一个自定义 Setter(如示例中的 AltStringSetter),并通过物料configure.propsoverride机制将其应用到具体组件属性上。文章以 docs/docs/api/setters.md 为主体骨架,并结合 packages/editor-core/src/di/setter.ts、packages/types/src/shell/api/setters.ts 等源码对底层行为进行印证。

适用说明:本文所述 API 自v1.0.0起可用;相关 TypeScript 类型定义位于 packages/types/src/shell/api/setters.ts。

模块简介:Setters 在低代码体系中的定位

在 lowcode-engine 的设计器(designer)中,每个组件属性的可视化编辑能力由Setter(设置器)提供:属性面板渲染某一项属性时,会根据物料配置选择一个对应的 Setter 组件来接收用户输入并回写值。setters模块就是负责这一能力的统一入口,其职责包括:

  • 注册设置器:把内置或自定义的 Setter 注册到全局注册表中;
  • 管理设置器:通过注册表按类型名存取、枚举所有已注册的 Setter;
  • 供给物料使用:注册成功后,物料协议中通过 setter 名称(字符串)即可引用对应设置器。

从 packages/editor-core/src/di/setter.ts 的实现可以看到,Setters 实例内部维护了一个Map<string, IPublicTypeRegisteredSetter & { type: string }>作为注册表,registerSettergetSettersMap都是直接读写这张表,getSetter则是按 key 查询。需要留意的是,官方文档所描述的settersAPI 是面向引擎使用者的公开接口(IPublicApiSetters),而 packages/editor-core/src/di/setter.ts 中还有一份供 DI 容器使用的Setters类实现,二者行为一致。

方法详解

getSetter(type):获取指定 setter

按 setter 类型名获取已注册的设置器,若未注册则返回null

/** * 获取指定 setter * get setter by type * @param type * @returns */ getSetter(type: string): IPublicTypeRegisteredSetter | null;
  • 参数type—— 注册时使用的 setter 类型名(字符串);
  • 返回值IPublicTypeRegisteredSetter | null,未找到时返回null

从源码看,该方法的实现为this.settersMap.get(type) || null(见 packages/editor-core/src/di/setter.ts),即直接从注册表取用。该接口常被用于运行时判断某个 setter 是否已注册、或获取其默认配置后再动态创建内容。

IPublicTypeRegisteredSetter的完整结构(见 packages/types/src/shell/type/registered-setter.ts):

字段类型说明
componentIPublicTypeCustomView设置器组件本体(React 元素或组件)
defaultPropsobject注册时携带的默认属性,渲染 setter 内容时会与传入 props 合并
titleIPublicTypeTitleContent设置器标题,MixedSetter 切换展示时使用
condition(field: IPublicModelSettingField) => boolean供 MixedSetter 判断该 setter 对当前字段是否可用
initialValueany \| ((field) => any)初始值,可为常量或根据字段动态计算
recommendboolean推荐标记,供 MixedSetter 优先级判断
isDynamicboolean标识是否为动态 setter,默认为true

getSettersMap():获取所有已注册的 setters

返回当前已注册的全部设置器映射表。

/** * 获取已注册的所有 settersMap * get map of all registered setters * @returns */ getSettersMap(): Map<string, IPublicTypeRegisteredSetter & { type: string; }>;
  • 返回值Map,key 为 setter 类型名,value 为注册条目,且额外带一个type字段标明其类型名(这是注册时由实现方自动附加的,见 packages/editor-core/src/di/setter.ts)。

该接口常用于调试、批量检查或动态遍历所有可用 setter。由于返回的是内部 Map 的引用,遍历时建议只读使用,避免意外污染全局注册表。

registerSetter(typeOrMaps, setter?):注册 setter

将一个(或一批)setter 注册到设计器,这是整个 API 的核心方法。

/** * 注册一个 setter * register a setter * @param typeOrMaps * @param setter * @returns */ registerSetter( typeOrMaps: string | { [key: string]: IPublicTypeCustomView | IPublicTypeRegisteredSetter }, setter?: IPublicTypeCustomView | IPublicTypeRegisteredSetter | undefined ): void;

两种调用形态:

  1. 注册单个 setter:第一个参数传类型名字符串,第二个参数传组件或完整注册描述:
    // 直接传组件(自定义视图) registerSetter('AltStringSetter', AltStringSetter); // 或传完整描述对象 registerSetter('StringSetter', { component: StringSetter, defaultProps: { placeholder: '请输入' }, title: '字符串', });
  2. 批量注册:第一个参数直接传一个映射对象,此时会忽略第二个参数,逐个 key 递归调用注册:
    registerSetter({ StringSetter, NumberSetter: { component: NumberSetter, title: '数字' }, });

从 packages/editor-core/src/di/setter.ts 的实现可以确认几个注册时的关键处理逻辑

  • 自定义视图自动包装:当传入的是IPublicTypeCustomView(React 元素或组件)而非完整描述对象时,会被自动包装为{ component: setter, title: setter.displayName || setter.name || 'CustomSetter' }。这意味着你在自定义组件上声明的static displayName会被自动用作 setter 标题;
  • initialValue 自动推导:若描述对象未显式提供initialValue,实现会尝试从组件上读取initial/Initial(或setter.type.initial/setter.type.Initial)并包装为基于当前字段值的函数:initialValue = (field) => initial.call(field, field.getValue())
  • 类型名回填:注册条目最终以{ type: typeOrMaps, ...setter }的形式存入 Map,保证每个条目都能反查自己的类型名。

相关类型

  • IPublicTypeRegisteredSetter(见 packages/types/src/shell/type/registered-setter.ts):注册条目的完整描述;
  • IPublicTypeCustomView(见 packages/types/src/shell/type/custom-view.ts):ReactElement | ComponentType<any>,即设置器组件本体。

补充:createSetterContent(已废弃)

IPublicApiSetters中还保留了一个标记@deprecated的方法createSetterContent(setter, props): ReactNode,用于把 setter(字符串或组件)解析为 React 节点。源码实现(见 packages/editor-core/src/di/setter.ts)展示了 setter 名称解析为组件的内部链路:先按名称取注册条目,合并defaultProps与传入 props,取component后通过createContent创建元素;此外,当props.value === undefined时会被删除,以保证 Fusion 表单组件能正确走defaultValue分支。虽然该 API 已废弃,但这段逻辑可以帮助理解 setter 从名称到渲染内容的完整流程。

使用示例一:注册官方内置 Setter 到设计器

引擎本身不携带完整的业务 Setter 集合,通常的做法是安装@alilc/lowcode-engine-ext(官方扩展包),在插件初始化时把其中的setterMap批量注册进设计器,同时把事件绑定面板、变量绑定面板注册到工作台。

import { setters, skeleton } from '@alilc/lowcode-engine'; import { setterMap, pluginMap } from '@alilc/lowcode-engine-ext'; import { IPublicModelPluginContext } from '@alilc/lowcode-types'; const SetterRegistry = (ctx: IPublicModelPluginContext) => { return { name: 'ext-setters-registry', async init() { // 注册 setterMap setters.registerSetter(setterMap); // 注册插件 // 注册事件绑定面板 skeleton.add({ area: 'centerArea', type: 'Widget', content: pluginMap.EventBindDialog, name: 'eventBindDialog', props: {}, }); // 注册变量绑定面板 skeleton.add({ area: 'centerArea', type: 'Widget', content: pluginMap.VariableBindDialog, name: 'variableBindDialog', props: {}, }); }, }; } SetterRegistry.pluginName = 'SetterRegistry'; await plugins.register(SetterRegistry);

要点说明:

  • setters.registerSetter(setterMap)即上文介绍的批量注册形态,一次把扩展包内所有内置 setter(字符串、数字、布尔、选择器等)写入注册表;
  • skeleton.add(...)将事件/变量绑定弹窗以Widget形式挂到centerArea,这两个面板本身也是配合对应 Setter 使用的配套能力(例如EventBindDialog供事件绑定类 Setter 打开);
  • 该插件注册后,物料协议中即可直接用这些 setter 的类型名,例如"setter": "StringSetter"

使用示例二:开发自定义 Setter

当内置 setter 无法满足需求时,可以开发自定义 setter。自定义 setter 本质上是一个受控的 React 组件,通过value接收当前属性值、通过onChange输出新值。下面是文档中的AltStringSetter完整实现:

import * as React from "react"; import { Input } from "@alifd/next"; import "./index.scss"; interface AltStringSetterProps { // 当前值 value: string; // 默认值 initialValue: string; // setter 唯一输出 onChange: (val: string) => void; // AltStringSetter 特殊配置 placeholder: string; } export default class AltStringSetter extends React.PureComponent<AltStringSetterProps> { componentDidMount() { const { onChange, value, defaultValue } = this.props; if (value == undefined && defaultValue) { onChange(defaultValue); } } // 声明 Setter 的 title static displayName = 'AltStringSetter'; render() { const { onChange, value, placeholder } = this.props; return ( <Input value={value} placeholder={placeholder || ""} onChange={(val: any) => onChange(val)} ></Input> ); } }

对自定义 setter 的几个约定,可结合源码加深理解:

  • displayName的重要性:注册时若直接传组件,displayName会被自动用作 setter 的title(见 packages/editor-core/src/di/setter.ts),并在 MixedSetter 切换等场景展示,务必声明;
  • value/onChange契约onChange是 setter 对外的唯一输出通道,引擎会把新值写回对应属性;initialValue只在字段无值时作为初始提示;
  • defaultValue兜底:示例在componentDidMount中检测到value == undefined且存在defaultValue时主动回调,把物料配置的默认值同步给引擎,这一模式可保证首次渲染即呈现合理取值。

注册自定义 Setter

开发完毕后,将其注册到设计器:

import AltStringSetter from './AltStringSetter'; import { setters } from '@alilc/lowcode-engine'; const { registerSetter } = setters; registerSetter('AltStringSetter', AltStringSetter);

注册之后,AltStringSetter这个名字就能在物料协议中被引用。需要提醒的是:注册应在属性面板实际渲染 setter 之前完成,通常放在引擎初始化阶段(如插件init中)。

在物料中应用自定义 Setter

核心配置:override 覆盖属性默认 setter

组件元数据(物料 schema)通过configure.props描述属性面板的编辑能力。默认情况下每个属性会按propType自动匹配 setter,如需强制使用自定义 setter,用override覆盖即可,核心配置如下:

{ "props": { "isExtends": true, "override": [ { "name": "type", "setter": "AltStringSetter" } ] } }
  • isExtends: true表示在继承默认 setter 匹配规则的基础上做扩展(而不是完全重写);
  • override数组中每一项通过name定位目标属性,setter字段既可以是已注册的 setter 类型名字符串,也可以是内联的 setter 配置对象或组件本身(IPublicTypeSetterType支持这几种形态,见 packages/types/src/shell/type/setter-type.ts);
  • setter字段若传配置对象,可进一步携带propsinitialValueisRequired等参数(完整字段见 packages/types/src/shell/type/setter-config.ts),例如:
    { "name": "type", "setter": { "componentName": "AltStringSetter", "props": { "placeholder": "请输入反馈类型" } } }

完整配置示例:Message 组件

把上面的机制放到一个完整的物料元数据中,为Message组件的type属性替换为自定义的AltStringSetter

{ "componentName": "Message", "title": "Message", "props": [ { "name": "title", "propType": "string", "description": "标题", "defaultValue": "标题" }, { "name": "type", "propType": { "type": "oneOf", "value": [ "success", "warning", "error", "notice", "help", "loading" ] }, "description": "反馈类型", "defaultValue": "success" } ], "configure": { "props": { "isExtends": true, "override": [ { "name": "type", "setter": "AltStringSetter" } ] } } }

需要说明的是:type属性的propTypeoneOf(枚举),默认会渲染为下拉选择类 setter;通过override覆盖为AltStringSetter后,属性面板会改以文本输入框的形式编辑该属性。这种"运行时替换 setter"的能力正是低代码平台实现属性编辑可定制化的关键。

源码视角:注册链路与底层原理小结

结合 packages/editor-core/src/di/setter.ts 的Setters类实现,把整条链路串起来:

  1. 注册registerSetter(typeOrMaps, setter)若收到对象则递归逐项注册;单个注册时先判断是否为自定义视图,是则自动补全componenttitle;再尝试从组件推导initialValue;最终以{ type, ...setter }写入全局settersMap
  2. 查询getSetter(type)直接查 Map,getSettersMap()返回整个 Map 供遍历;
  3. 渲染:属性面板渲染时(内部链路经createSetterContent,已废弃但逻辑仍在)按名称取出注册条目,合并defaultProps与当前 props,用createContent创建 setter 组件实例,并保持value/onChange双向绑定。

类型定义层面,packages/types/src/shell/api/setters.ts 是公开 API 契约的唯一来源,配套的IPublicTypeRegisteredSetterIPublicTypeCustomViewIPublicTypeSetterConfig分别定义了注册条目、组件形态与 setter 配置项的约束,开发自定义 setter 时建议以这些类型作为编写依据,以获得完整的类型提示与编译期校验。

常见问题与排查建议

  • 物料中引用了 setter 但属性面板空白:优先确认registerSetter是否在渲染前执行成功,可通过setters.getSetter('你的类型名')验证是否返回了注册条目;
  • 自定义 setter 标题不显示:检查组件是否声明static displayName,未声明时会退化为组件name'CustomSetter'
  • 初始值不生效:确认注册条目未显式设置initialValue,且组件上提供了initial/Initial静态方法,或改为在componentDidMount中根据defaultValue主动回调(如 AltStringSetter 示例);
  • 批量注册被忽略:当第一个参数为对象时,实现会遍历对象自身的 key 逐项注册,请确保传入的是普通对象而非包含不可枚举属性的 Map 或类实例。

【免费下载链接】lowcode-engineAn enterprise-class low-code technology stack with scale-out design / 一套面向扩展设计的企业级低代码技术体系项目地址: https://gitcode.com/GitHub_Trending/lo/lowcode-engine

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询