11 KiB
Bricks UI 类型定义与构建系统技术文档
本文档描述了 bricks.UiTypesDef 类及其相关工厂函数和构建器,用于实现基于 uitype 的视图(View)和输入控件(Input)的动态创建机制。该系统支持灵活扩展不同数据类型的 UI 表现形式。
目录
1. 概述
bricks.UiTypesDef 是一个管理 UI 类型映射 的核心类,它将特定的数据类型(如 str, int, password 等)与对应的 视图构建器(viewBuilder) 和 输入构建器(inputBuilder) 关联起来。
通过注册不同的构建器函数,可以实现对字段描述(desc)和记录数据(rec)自动生成 UI 控件的能力。
系统提供两个主要工厂函数:
viewFactory: 创建只读文本显示控件inputFactory: 创建可编辑输入控件
默认情况下,所有未匹配的类型会尝试回退到 'str' 类型处理。
2. 核心类:UiTypesDef
bricks.UiTypesDef = class {
constructor(opts)
}
constructor(opts)
初始化 UiTypesDef 实例。
参数
| 参数名 | 类型 | 说明 |
|---|---|---|
opts |
Object | 可选配置对象(当前未使用) |
属性
this.uitypes: 存储每种uitype对应的构建器对象,结构如下:{ uitype: { viewBuilder: Function, inputBuilder: Function } }
set(uitype, viewBuilder, inputBuilder)
注册一个 UI 类型的视图和输入构建器。
参数
| 参数名 | 类型 | 必需 | 说明 |
|---|---|---|---|
uitype |
String | 是 | UI 类型名称,例如 'str', 'int' |
viewBuilder |
Function | 否 | 用于生成只读视图的函数 |
inputBuilder |
Function | 否 | 用于生成可编辑输入控件的函数 |
若对应
uitype尚未存在,则自动创建容器对象。
get(uitype)
获取指定 uitype 的 [viewBuilder, inputBuilder] 数组。
返回值
- 成功时返回
[viewBuilder, inputBuilder] - 失败时返回
(null, null)(注意:原代码有误,实际返回[null, null]更合理)
示例
const [viewFn, inputFn] = bricks.uitypesdef.get('str');
getViewBuilder(uitype)
获取指定类型的视图构建器函数。
参数
| 参数名 | 类型 | 说明 |
|---|---|---|
uitype |
String | 要查询的 UI 类型 |
返回值
Function:视图构建器- 若不存在则返回
undefined
⚠️ 注意:原代码中若找不到返回的是
this.uitypes[uitype].viewBuilder,即可能为undefined,但注释写成返回Null,可能是笔误。
getInputBuilder(uitype)
获取指定类型的输入构建器函数。
参数
| 参数名 | 类型 | 说明 |
|---|---|---|
uitype |
String | 要查询的 UI 类型 |
返回值
Function:输入构建器- 若不存在则返回
Null(注意:JavaScript 中应为null,而非首字母大写的Null—— 原代码此处可能存在错误)
setViewBuilder(uitype, Builder)
仅设置某个 uitype 的视图构建器。
参数
| 参数名 | 类型 | 说明 |
|---|---|---|
uitype |
String | UI 类型 |
Builder |
Function | 视图构建函数 |
如果该
uitype无条目,则先初始化空对象。
setInputBuilder(uitype, Builder)
仅设置某个 uitype 的输入构建器。
参数
| 参数名 | 类型 | 说明 |
|---|---|---|
uitype |
String | UI 类型 |
Builder |
Function | 输入构建函数 |
同上,若不存在则先创建占位对象。
3. 工厂函数
bricks.viewFactory(desc, rec)
根据字段描述和数据记录生成对应的只读视图组件。
参数
| 参数名 | 类型 | 说明 |
|---|---|---|
desc |
Object | 字段描述对象,必须包含 .uitype 和 .name |
rec |
Object | 数据记录对象,字段值从中提取 |
流程
- 提取
desc.uitype - 查找注册的
viewBuilder - 若未找到,尝试使用
'str'类型作为默认 fallback - 若仍无 builder,返回
Null(⚠️ 应为null) - 调用 builder 生成控件并返回
返回值
- UI 控件实例(如
Text组件),或null
示例
const widget = bricks.viewFactory({ uitype: 'int', name: 'age' }, { age: 25 });
// 返回右对齐的文本 "25"
bricks.inputFactory(desc, rec)
生成可编辑的输入控件。
参数
| 参数名 | 类型 | 说明 |
|---|---|---|
desc |
Object | 字段描述 |
rec |
Object | 当前数据记录 |
流程
- 获取
uitype - 查找
inputBuilder,失败则 fallback 到'str' - 若无 builder,返回
Null(⚠️ 同样应为null) - 调用 builder 并返回结果
返回值
- 输入控件实例(如
UiStr,UiPassword),或null
示例
const input = bricks.inputFactory({ uitype: 'password', name: 'pwd' }, {});
// 返回 UiPassword 控件
4. 内置构建器
通用辅助函数
buildText(text, halign)
创建一个标准化的文本控件。
参数
| 参数名 | 类型 | 说明 |
|---|---|---|
text |
String | 显示文本内容 |
halign |
String | 水平对齐方式,仅支持 'left' 或 'right',其他值默认为 'left' |
返回值
Text实例,具有以下属性:{ text: text || '', overflow: 'hidden', wrap: true, halign: 'left' // 固定左对齐?注意这里硬编码了 left! }
❗ 注意:尽管参数允许传入
halign,但在构造Text时却固定写死为'left',这可能导致逻辑不一致!
建议修正为:
halign: halign // 而非 'left'
字符串类型 (str)
strViewBuilder(desc, rec)
生成字符串类型的只读视图。
实现
- 从
rec[desc.name]取值 - 使用
buildText(v, 'left')显示,左对齐
注册
bricks.uitypesdef.setViewBuilder('str', strViewBuilder);
strInputBuilder(desc, rec)
生成字符串输入控件。
实现
- 设置
desc.value为当前字段值(⚠️ 原代码中desc[value]存在语法错误!应为desc.value) - 返回
new UiStr(desc)
错误提示
desc[value] = v; // ❌ 语法错误!value 未定义
✅ 正确应为:
desc.value = v;
注册
bricks.uitypesdef.setInputBuilder('str', strInputBuilder);
密码类型 (password)
passwordViewBuilder(desc, rec)
显示掩码文本 ******,保护隐私。
实现
- 忽略真实值,始终显示六个星号
- 调用
buildText('******')
注册
bricks.uitypesdef.setViewBuilder('password', passwordViewBuilder);
passwordInputBuilder(desc, rec)
生成密码输入框。
实现
- 直接返回
new UiPassword(desc) - 不依赖
rec值(由组件自身管理)
注册
bricks.uitypesdef.setInputBuilder('password', passwordInputBuilder);
整数类型 (int)
intViewBuilder(desc, rec)
将数值转为字符串,并右对齐显示。
实现
v = rec[desc.name] + ''(强制转字符串)- 调用
buildText(v, 'right')
注册
bricks.uitypesdef.setViewBuilder('int', intViewBuilder);
浮点数类型 (float)
floatViewBuilder(desc, rec)
格式化浮点数,保留小数位后显示。
参数扩展
desc.dec_len:指定小数位数,默认为2
实现
v = rec[desc.name];
v = v.toFixed(desc.dec_len || 2); // 格式化
v = v + ''; // 转字符串
return buildText(v, 'right'); // 右对齐
注册
bricks.uitypesdef.setViewBuilder('float', floatViewBuilder);
编码/字典类型 (code)
适用于下拉选择、字典项等场景的只读显示。
codeViewBuilder(desc, rec)
参数处理
- 克隆
desc为opts - 若存在
uiparams,将其属性合并到opts - 支持两个字段名优先级:
textFeild(拼写疑似错误,应为textField)valueField
查找逻辑
v = rec[desc.textFeild || 'text']
if (!v) v = rec[desc.valueField || 'value']
⚠️ 注意:
textFeild很可能是拼写错误,应为textField
显示
- 左对齐文本控件
注册
bricks.uitypesdef.setViewBuilder('code', codeViewBuilder);
已知问题与改进建议
| 问题 | 说明 | 建议修复 |
|---|---|---|
desc[value] = v |
JavaScript 语法错误 | 改为 desc.value = v |
return Null |
非法标识符(应为 null) |
所有 Null → null |
halign:'left' in buildText |
忽略参数,始终左对齐 | 改为 halign: halign |
textFeild 拼写错误 |
可能导致字段无法正确识别 | 改为 textField |
默认 fallback 使用 'str' |
合理但需确保 'str' 已注册 |
初始化时必须保证基础类型存在 |
总结
本模块实现了基于 uitype 的 UI 构建策略模式,具备良好的扩展性:
- 新增类型只需调用
setViewBuilder/setInputBuilder - 工厂函数统一接口调用
- 支持 fallback 机制增强健壮性
适合用于表单渲染、列表展示等需要动态 UI 生成的场景。
✅ 维护建议:增加类型校验、异常捕获、单元测试以提升稳定性。