Skip to content

容易误解的地方 ​

把机制按章节拆开之后,最容易出问题的不是复杂算法,而是几个边界。下面这些点值得在设计 自定义形状和宿主时先看一遍。

1. 注册表不是一个默认全量的全局表 ​

createRegistry() 从空表开始。想保留矩形、椭圆、路径和内置 marker,必须显式写:

ts
const registry = createRegistry({ base: builtinRegistry });

漏掉 base 不会让所有东西立刻崩溃,但图会少掉内置形状或箭头,随后出现回落和诊断。

2. measure 和 render 可能各说各话 ​

布局只看 measure,不会调用 render。如果 render 画出了超过盒子的内容,布局不知道, 父容器、连线、viewBox 都可能对不上。反过来,render 也不能通过改坐标修正布局。

一句话:大小和位置在 measure/layout 决定,render 只负责画。

3. 自定义边要自己处理标签 ​

边注册项的 render 拿到 ctx.labelOut,但库不会自动替所有自定义边画标签。只在文档里写 label,却没有在边注册项里输出标签,标签就不会出现。

这是当前 API 最容易让人意外的一点。以后可以加一个明确的“自动标签”选项,但现在应把 标签当成边画法的一部分。

4. pins 是坐标,但它仍然是文档字段 ​

设计上文档表达意图,而 pins 又确实是绝对坐标。它只服务于 explicit 引擎,其他引擎不会 自动消费它。看到 pins 时,把它理解成“显式布局的参数”,而不是每个节点都有的位置属性。

5. 注册同名 type 会直接覆盖 ​

registerShape("card", a) 之后再注册 "card",后一个会替换前一个。注册表不认为这是错误, 也不会发诊断。组合多个来源时,最好在应用层维护一份自己的 type 清单。

6. 场景 key 不是调试信息 ​

key 决定增量更新是否能复用旧零件。随手改名、用随机值或数组下标,会让宿主把正常修改当成 整棵子树重建。ctx.out.key 生成的 key 是契约的一部分,不只是给人看的标签。

值得继续改的地方 ​

这些是写文档时暴露出来的 API 反思,不代表当前用法有错:

现象可以考虑的方向
自定义边容易忘记画标签给 EdgeSpec 增加显式的自动标签约定
同名 type 覆盖没有提示注册时返回冲突诊断,或在开发模式下警告
空注册表与内置注册表差异大提供更直白的 extendBuiltinRegistry() 入口
schema 在 layout 和 build 各解析一次抽出共享的归一化入口,并为自定义形状补检查器

这些改动只有在能保持“文档 → 几何 → 场景 → 介质”的边界时才值得做。否则只是把一个问题 藏到另一层。

MIT License