拼装比传参更少歧义
别名: 复合组件 · 拼装式 API · compound component · composition API
概念解释
拼装(assembly over props)把组件的结构写成可见的子节点树:对话框由标题、躯干、动作栏三块拼起来,每一块在标记里占一个位置。传参把同一结构压进扁平属性:showHeader、footerActions、extra。拼装更少歧义,是因为树上的每个位置对应一个真实子组件,阅读标记就能看见「这里是动作、那里是标题」;扁平属性则允许同一个布尔被多种意图占用,调用点必须猜作者当时的意思。
歧义发生在接口被阅读的那一刻,不是发生在渲染之后。extra={true} 可以表示角标、可以表示溢出菜单、也可以表示「请把默认那块藏起来」。写成 <Card.Badge> 或 <Card.Overflow>,意图跟节点一起出现,不再共用一个槽位名。
机制
属性表是一张无序的键值表,键之间没有空间关系。人读属性时,只能靠命名约定重建「谁挨着谁」。拼装把空间关系写回树:子节点的种类和顺序就是结构。编译器和编辑器也能看见这棵树,补全给出的是合法子组件,而不是一份无限延伸的布尔清单。
传参便宜的一面是调用短。短的代价是冲突:新产品要在「标题右侧」放东西,属性表里往往已有一个含义模糊的 extra,于是再叠 extraRight、headerAddon。每个新键都是一次对旧键的重新解释。拼装让新产品加一个子组件类型,旧调用不必重新理解旧键。结构从「猜键名」变成「看树上有没有这块」。
边界
结构本身只有一两处开关、且开关语义封闭时,传参更清楚——按钮的 disabled 不值得做成 <Button.Disabled>。动画、纯样式钩子没有可拼的子角色。服务端只输出属性字典、没有组件树的通道上,拼装无法落地。子组件数量涨到与页面区块一一对应时,拼装已经滑成了把页面拆进库,那是边界划错,不是拼装本身的优点。
怎么落地
- 把「位置」做成子组件(
Dialog.Title、Dialog.Actions),把「值」留成属性(文案字符串、选中 id)。位置用拼装表达,值用传参表达。 - 审查现有属性表:凡是一个键能被两个产品经理解释成两件事的,拆成两个子组件,删掉这个键。
- 在编辑器补全里只暴露合法子组件,不把内部实现组件放到同一补全面板。
- 验证:把一处真实调用的全部属性名涂黑,只留标记树。没看过文档的人若能指出哪块是标题、哪块是动作,拼装成立。若必须去翻属性默认值才能知道画面上有没有顶栏,说明结构还埋在参数里。再并列写出传参版与拼装版同一界面:数一数有多少个键需要口头解释,那个数字就是歧义存量。