news 2026/9/14 15:09:54

lowcode-engine 属性集模型(Props Model)完全指南:IPublicModelProps 属性、方法与实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
lowcode-engine 属性集模型(Props Model)完全指南:IPublicModelProps 属性、方法与实战

lowcode-engine 属性集模型(Props Model)完全指南:IPublicModelProps 属性、方法与实战

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

属性集(Props)是 lowcode-engine 文档模型中承载节点组件属性的核心数据结构。本篇指南以官方 API 文档 props.md 为骨架,结合 Props 实现类 与 Prop 实现类 的源码,系统讲解IPublicModelProps的全部属性与方法、路径寻址语法、普通属性与扩展属性(extra prop)的区别,以及如何在插件与设置器中安全读写属性值。读完本文,你将能够熟练使用属性集模型完成组件属性的增删改查、嵌套路径操作与 schema 导出。

基本介绍:什么是属性集模型

在 lowcode-engine 中,每个文档节点(Node)都对应一份组件配置,而这份配置的主体就是属性集(Props)。属性集模型IPublicModelProps是节点props字段的面向 Shell 层的公开抽象,定义于 packages/types/src/shell/model/props.ts,其内部实现为 designer 包中的Props类(props.ts)。

从类型定义看,IPublicModelProps继承自IBaseModelProps<IPublicModelProp>,即它管理的是一个由若干IPublicModelProp(单个属性模型)组成的集合。与之配套的类型还包括:

  • IPublicModelProp:单个属性的公开模型,提供getValue/setValue/getAsString等方法;
  • IPublicModelNode:属性集所属的节点模型。

属性集模型于v1.0.0随 Shell 层模型体系一同发布(@since v1.0.0),并在 v1.1.0 中补充了hasadd两个方法(@since v1.1.0)。

从底层实现看,Props类在内部维护一个items: IProp[]数组,并通过@obx.shallow@computed保持响应式能力——当某个属性的值发生变化时,会通过Prop#emitChange触发GlobalEvent.Node.Prop.InnerChange事件并回调节点自身的emitPropChange(见 prop.ts),从而驱动设计器画布、属性面板的实时联动。

属性(Properties)

IPublicModelProps暴露了三个只读属性,用于标识属性集自身的身份与归属。

id

@type {string}

属性集实例的唯一标识。底层实现中由uniqueId('props')生成(见 props.ts),在文档生命周期内保持稳定,可用于在调试或持久化场景中区分不同的属性集实例。

path

@type {string[]}

返回当前属性集的路径。对于节点根级属性集,其path为空数组[](底层Props类中readonly path = []);对于嵌套属性(如prop.get(...)返回的子级Prop),其path由父级路径拼接当前 key 得到(见 prop.ts)。路径以数组形式表达,便于程序化地追踪属性在 schema 中的位置。

node

@type {IPublicModelNode | null}

返回当前属性集所属的节点实例。Shell 层实现通过ShellNode.create(this[propsSymbol].getNode())将内部节点包装为公开的IPublicModelNode(见 packages/shell/src/model/props.ts);若底层节点不存在,则返回null。这一属性在需要从属性集反查节点、进而操作节点本身(如获取节点componentNamechildren)时非常有用。

路径寻址语法:a / a.b / a.0

属性集模型的所有方法都围绕**路径(path)**展开,因此先理解路径语法是关键。底层Props#get实现(见 props.ts)对路径的解析规则如下:

  • 单段路径:如a,直接在当前属性集中按 key 查找;
  • 多段路径:如a.b,先取第一段a作为入口,剩余b递归下钻;
  • 数组下标:如a.0,当某段属性是列表类型(list)时,数字段会被解析为数组下标——Prop#get中通过isValidArrayIndex(entry, this.size)校验并索引(见 prop.ts)。

例如对 schema:

{ "props": { "title": "按钮", "style": { "color": "red" }, "dataSource": [{ "name": "a" }, { "name": "b" }] } }

getPropValue('title')getPropValue('style.color')getPropValue('dataSource.1.name')分别可命中普通属性、嵌套对象字段和列表元素。

需要特别说明get的第二个参数createIfNone(默认为false):当目标属性不存在且createIfNonetrue时,会创建一个值为UNSET的占位Prop并写入集合(见 props.ts);若为false则返回nullsetPropValue内部正是利用getProp(path, true)实现"不存在即创建再写入"的语义。

方法(Methods)

getProp

获取指定 path 的属性模型实例。

/** * 获取指定 path 的属性模型实例 * get prop by path * @param path 属性路径,支持 a / a.b / a.0 等格式 */ getProp(path: string): IPublicModelProp | null;

返回类型为 IPublicModelProp。Shell 层通过ShellProp.create(...)包装内部 Prop(见 packages/shell/src/model/props.ts)。拿到属性实例后,可继续调用其getValue()/setValue()/getAsString()等方法完成更精细的操作。注意:getProp不会创建不存在的属性,找不到时返回null

getPropValue

获取指定 path 的属性模型实例值。

/** * 获取指定 path 的属性模型实例值 * get value of prop by path * @param path 属性路径,支持 a / a.b / a.0 等格式 */ getPropValue(path: string): any;

这是最常用的读值方法。Shell 层实现为this.getProp(path)?.getValue()(见 packages/shell/src/model/props.ts),底层getValue实际执行export(IPublicEnumTransformStage.Serilize),即返回序列化阶段的值(见 prop.ts)。返回值类型为any:可能是字面量、{ type: 'JSExpression', value: 'state.x' }表达式、对象、数组或 JSSlot 结构。

getExtraProp

获取指定 path 的属性模型实例。

/** * 获取指定 path 的属性模型实例, * 注:导出时,不同于普通属性,该属性并不挂载在 props 之下,而是与 props 同级 * get extra prop by path * @param path 属性路径,支持 a / a.b / a.0 等格式 */ getExtraProp(path: string): IPublicModelProp | null;

getExtraPropValue

获取指定 path 的属性模型实例值。

/** * 获取指定 path 的属性模型实例值 * 注:导出时,不同于普通属性,该属性并不挂载在 props 之下,而是与 props 同级 * get value of extra prop by path * @param path 属性路径,支持 a / a.b / a.0 等格式 */ getExtraPropValue(path: string): any;

扩展属性(extra prop)是理解属性集的关键概念之一。它用于承载那些不属于组件 props 配置、但与节点生命周期/设计器行为强相关的元数据,例如condition(条件渲染)、loop(循环)、hidden(隐藏)、isLocked(锁定)、title等。在Node构造函数中,这些内置指令正是通过props.add(..., getConvertedExtraKey('condition'))等方式写入属性集的(见 node.ts)。

底层实现中,扩展属性的 key 带有___前缀:getConvertedExtraKey(key)condition转换为___condition___,而getOriginalExtraKey负责反向还原(见 props.ts)。Shell 层的getExtraProp即先转换 key 再查找(见 packages/shell/src/model/props.ts)。

其"导出时与 props 同级"的语义体现在Props#export中:导出时,key 以___开头的属性会被剥离前缀并归入独立的extras对象,而普通属性留在props对象内(见 props.ts),最终节点 schema 形如:

{ "componentName": "Button", "props": { "children": "确定" }, "condition": true, "loop": { "type": "JSExpression", "value": "state.list" } }

其中conditionloopprops同级。因此,读写这类字段必须使用getExtraProp/getExtraPropValue/setExtraPropValue,而不是普通属性方法。

setPropValue

设置指定 path 的属性模型实例值。

/** * 设置指定 path 的属性模型实例值 * set value of prop by path * @param path 属性路径,支持 a / a.b / a.0 等格式 * @param value 值 */ setPropValue(path: string, value: IPublicTypeCompositeValue): void;

value的类型为 IPublicTypeCompositeValue,即复合类型,包含:

  • 任意 JSON 值(string/number/boolean/null/ 普通对象 / 数组);
  • IPublicTypeJSExpression(如{ type: 'JSExpression', value: 'this.state.x' });
  • IPublicTypeJSFunction(函数表达式);
  • IPublicTypeJSSlot(插槽,如{ type: 'JSSlot', value: [{ componentName: 'Text' }] });
  • 由上述类型任意嵌套组成的复合数组/复合对象。

底层Prop#setValue会根据值形态自动判定属性类型:字符串/数字/布尔归类为literal,数组为listJSSlotslotJSExpressionexpression,普通对象为map(见 prop.ts)。设置完成后会触发setupItems重建子属性并派发变更事件,保证响应式链路不中断。实测示例见 props.test.ts:props.setPropValue('a', 2)getPropValue('a')返回2

setExtraPropValue

设置指定 path 的属性模型实例值(扩展属性版)。

/** * 设置指定 path 的属性模型实例值 * set value of extra prop by path * @param path 属性路径,支持 a / a.b / a.0 等格式 * @param value 值 */ setExtraPropValue(path: string, value: IPublicTypeCompositeValue): void;

Shell 层实现先经getConvertedExtraKey转换 key,再调用内部setValue(见 packages/shell/src/model/props.ts)。典型用途如设置节点的condition(条件渲染开关)、loop(循环数据源)等指令级属性。与setPropValue相同,value同样支持 IPublicTypeCompositeValue 复合类型。

has

当前 props 是否包含某 prop。

/** * 当前 props 是否包含某 prop * check if the specified key is existing or not. * @param key * @since v1.1.0 */ has(key: string): boolean;

@since v1.1.0。底层实现直接查询内部maps集合(见 props.ts),时间复杂度 O(1)。注意:has只判断 key 是否存在,不校验值是否为UNSET(未设置占位)。在Node初始化指令时,正是用props.has(getConvertedExtraKey('condition'))判断是否需要补默认值(见 node.ts)。

add

添加一个 prop。

/** * 添加一个 prop * add a key with given value * @param value * @param key * @since v1.1.0 */ add(value: IPublicTypeCompositeValue, key?: string | number | undefined): any;

@since v1.1.0key可选:传入时以指定 key 新增属性,不传则由实现决定(如列表场景按序号)。底层Props#add会创建一个新Prop并追加到items,返回该 Prop 实例(见 props.ts),因此可链式调用返回值的setValue等方法。value同样为复合类型。

实战:在插件/设置器中读写属性

将上述 API 组合起来,即可在插件或自定义设置器中完成常见的属性操作。以下示例基于documentModel与节点模型:

// 获取当前选中节点 const node = documentModel.getNode('xxx') || documentModel.selection.getNodes()[0]; const props = node.props; // IPublicModelProps // 1. 读取普通属性与嵌套路径 const title = props.getPropValue('title'); const color = props.getPropValue('style.color'); // 2. 写入属性(不存在则自动创建) props.setPropValue('title', '新标题'); props.setPropValue('style.color', '#ff6600'); // 3. 读取表达式属性(复合值) const expr = props.getPropValue('visible'); // expr => { type: 'JSExpression', value: 'state.visible' } // 4. 操作扩展属性(与 props 同级导出的指令字段) const cond = props.getExtraPropValue('condition'); // true / false / 表达式 props.setExtraPropValue('condition', false); // 让组件在渲染阶段不展示 props.setExtraPropValue('loop', { type: 'JSExpression', value: 'state.list' }); // 5. 判断与新增 if (!props.has('dataSource')) { props.add([], 'dataSource'); // 新增一个空数组属性 } // 6. 通过 getProp 拿到实例做精细操作 const prop = props.getProp('title'); if (prop) { const s = prop.getAsString(); // 字面量转字符串 prop.setValue('又一个标题'); }

几点实战建议:

  • 优先使用getPropValue/setPropValue而非先getProp再取值,前者写法更简洁且自带安全防护;
  • 在设置器(Setter)内部通常通过SettingTarget操作属性,其底层同样委托到本文所述属性集模型(见 prop.ts 中的getPropValue/setPropValue/clearPropValue注释@see SettingTarget);
  • 修改属性后无需手动刷新画布,变更事件(GlobalEvent.Node.Prop.InnerChange)会自动驱动相关视图更新;
  • 若要移除某属性,可先getProp(path)拿到实例再调用其unset()(标记为未设置)或remove()(从父级移除),见 prop.ts 与 prop.ts。

与节点模型的关系及内部机制

属性集不是孤立存在的,它与节点模型深度绑定:

  1. 初始化Node构造函数中通过new Props(this, props, extras)创建属性集,其中propsextras来自 schema 解构(const { componentName, id, children, props, ...extras } = nodeSchema,见 node.ts),这正是"扩展属性与 props 同级"在导入方向的体现;
  2. 查询转发:节点上的getProp/getPropValue/setPropValue/setExtraPropValue等方法均转发给this.props(见 node.ts),因此既可通过node.props也可直接通过节点方法操作属性;
  3. 导出(序列化)Props#export(stage)依据map/list两种存储形态分别导出为props对象或props数组,并将___前缀的扩展属性剥离到extras(见 props.ts);Prop#export则按literal / expression / slot / map / list五种类型递归导出(见 prop.ts),其中JSSlotRender阶段还会附加paramsid等运行时信息;
  4. 响应式与变更:属性值变更经由emitChange抛出Node.Prop.InnerChange事件并回调owner.emitPropChange(见 prop.ts),同时Props#import/merge支持整体替换与增量合并,配合@action保证事务一致性。

测试佐证

属性集的行为在仓库中有完整测试覆盖:props.test.ts 验证了getNodegetgetPropValuesetPropValue、嵌套路径(z.z1)、自动创建属性(get('l', true))等核心能力;prop.test.ts 则覆盖单个PropsetValue、类型判定、unsetremoveexport等行为。阅读测试用例是理解属性集边界行为(如UNSET占位、createIfNone语义、列表下标合法性校验)的最佳途径。

小结

属性集模型IPublicModelProps是 lowcode-engine 中连接 schema、文档节点与 UI 面板的枢纽:通过a / a.b / a.0的统一路径语法,配合getProp/getPropValue/setPropValue与扩展属性系列方法,开发者可以精确、安全地操作任意节点的组件配置;理解其底层Props/Prop实现、___前缀的扩展属性机制与复合值类型系统,则能帮助你在插件开发、自定义 Setter、schema 迁移等场景中写出更可靠的低代码扩展代码。

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

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/14 15:09:34

Anaconda3 conda命令详解:环境管理与包管理实战指南

1. Anaconda3 核心命令&#xff1a;环境管理才是重头戏1.1 创建与删除环境&#xff1a;别再把 base 环境弄乱了很多人把 Anaconda 当成一个普通 Python 安装包&#xff0c;装完就一直在 base 环境里用pip install装库。这其实是效率最低、风险最高的用法。我刚开始处理数据那会…

作者头像 李华
网站建设 2026/9/14 15:09:18

BLE指令驱动语音播报:超低功耗语音触发技术实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/14 15:08:59

美食菜谱微信小程序开发实战:从解压到搜索收录

简介&#xff1a;这是一份用于学习微信小程序开发的完整美食菜谱项目源码&#xff0c;适合初、中级开发者以及想快速上手小程序实战的学员。压缩包内共四十九个文件&#xff0c;以页面逻辑脚本、界面结构描述、样式表和配置文件为主&#xff0c;并配有大量菜谱与界面图片&#…

作者头像 李华
网站建设 2026/9/14 15:08:59

rdseed详解:Linux下SEED转SAC的编译与使用

简介&#xff1a;rdseedv5.3.1是一款面向Linux平台的地震数据格式转换工具&#xff0c;主要完成SEED标准格式到SAC分析格式的转换&#xff0c;核心服务对象是地震台网数据处理人员、科研院所研究者以及需要批量转换波形数据的工程技术人员。该压缩包共含454个文件&#xff0c;整…

作者头像 李华
网站建设 2026/9/14 15:08:40

MATLAB实现自适应CNN:注意力机制驱动的图像分类与特征提取

简介&#xff1a;基于MATLAB的自适应CNN图像分类与特征提取系统为一套面向图像处理与深度学习入门者的完整示例代码包&#xff0c;解决传统CNN对不同类型、不同分辨率图像自适应能力不足的问题。包内共2个文件&#xff0c;包括可直接运行的主程序main.m&#xff0c;以及详细说明…

作者头像 李华
网站建设 2026/9/14 15:06:08

猪脸识别实战:细粒度图像分类与VGG/ResNet迁移学习

简介&#xff1a;这是京东JDD大赛猪脸识别项目的完整源码与说明文档&#xff0c;面向计算机视觉方向的学生、竞赛选手和需要课程设计或毕业设计参考的开发者&#xff0c;旨在帮助读者掌握基于深度学习的猪只个体识别方案。压缩包共61个文件&#xff0c;大小5.62MB&#xff0c;包…

作者头像 李华