渲染内建
本文档收敛 Dujie 中直接参与最终渲染结果的语言内建:
mainelementtextfragmentcomment
它们不按普通函数库看待,而是渲染系统和宿主平台之间的语言级边界。
widget
widget 是抽象渲染结果类型。
它不是某一种具体宿主节点类型,而是“可被渲染系统接受的 UI 树值”。
当前规则:
widget是一等类型- 可以赋值、传参、返回
- 可以放入
list<widget> - 可以作为
struct字段或opt<widget>的内部类型 - 不支持比较
- 不能作为
map的 key
组件函数
组件函数的判定规则:
- 只有显式返回类型恰好为裸
widget的函数才算组件函数 list<widget>、opt<widget>、map<string, widget>等都不算组件函数返回类型- 判定只看显式签名,不靠函数体推导
组件函数本身仍然是普通 Dujie 函数,只是返回 widget。
保留内建名
第一阶段将以下名字视为保留内建名:
mainelementtextfragmentcomment
用户不能定义同名顶层函数覆盖它们。
main
main 是入口 intrinsic,不等同于普通导出函数。
规则:
main的返回类型必须显式写为裸widgetmain的参数写法按普通 Dujie 函数规则处理main不能是泛型函数
也就是说,这些都可以是合法的语言层声明:
func main() -> widget
func main(title: string, count: opt<int>) -> widget
func main({ title: string, count: int = 0 }) -> widget
入口适配层
语言层允许用户自由书写 main 参数形状,但宿主或代码生成层需要提供与之匹配的入口适配。
当前约定是:
- 如果
main使用位置参数,Rust 侧按顺序暴露对应参数 - 如果
main使用具名参数,Rust 侧可以生成对应的参数结构体来承接输入 opt<T>在 Rust 侧映射为对应的Option<T>- 默认值由生成的适配层补齐,不要求 Rust 调用方手动补默认值
例如,类似下面的 Dujie 入口:
func main(title: string, count: opt<int>) -> widget
可以在 Rust 侧暴露为“顺序参数”风格入口;而:
func main({ title: string, count: int = 0 }) -> widget
可以在 Rust 侧暴露为“参数结构体”风格入口。
动态边界示例
如果用户本身就把 main 写成动态边界形式:
func main(props: map<string, any>) -> widget
则:
props["k"]缺 key 时panic- 从
any中取具体值时,使用is做显式收窄
text
签名:
text(value: string) -> widget
职责:
- 构造文本节点
- 不承担格式化职责
fragment
签名:
fragment(children: list<widget>) -> widget
职责:
- 聚合多个子节点
- 不承诺生成真实宿主节点
规则:
children可以为空- 嵌套
fragment在渲染语义上可展平 fragment([])表示不产生可见子节点
comment
签名:
comment(value: string) -> widget
职责:
- 构造注释或调试节点
规则:
- 不影响布局
- 不影响命中测试
- 不影响事件
- 不影响可访问性结构
- 后端可以选择保留或擦除
element
第一阶段按具名参数函数理解:
func element({
name: string,
props: map<string, any> = {},
children: list<widget> = [],
}) -> widget
规则:
name必填props默认空mapchildren默认空listprops是宿主边界属性字典children是显式子节点列表
第一阶段不引入联合类型,因此 element.props 保持:
map<string, any>
这代表宿主边界的开放属性集合,不代表普通语言内部推荐的静态数据模型。
渲染树语义
普通组件函数最终会展开成由 intrinsic 构成的渲染树。
语言层关心的是渲染语义,而不是中间组件调用层级。
子节点顺序
children顺序有语义- 子节点不能重排
fragment 展平
如果某个子节点是 fragment(...),渲染时可以将其展平成内部子节点序列。
也就是说,这两者在渲染层可以视为等价:
fragment(children: [a, b])
fragment(children: [fragment(children: [a]), b])
当前不定义
第一阶段不定义:
widget的比较或相等性- diff 语义
- 渲染后端的具体 Android / iOS / Web 映射细节
- 响应式更新机制