R1.11.2assembly over props设计

拼装比传参更少歧义

别名: 复合组件 · 拼装式 API · compound component · composition API

概念解释

拼装(assembly over props)把组件的结构写成可见的子节点树:对话框由标题、躯干、动作栏三块拼起来,每一块在标记里占一个位置。传参把同一结构压进扁平属性:showHeaderfooterActionsextra。拼装更少歧义,是因为树上的每个位置对应一个真实子组件,阅读标记就能看见「这里是动作、那里是标题」;扁平属性则允许同一个布尔被多种意图占用,调用点必须猜作者当时的意思。

歧义发生在接口被阅读的那一刻,不是发生在渲染之后。extra={true} 可以表示角标、可以表示溢出菜单、也可以表示「请把默认那块藏起来」。写成 <Card.Badge><Card.Overflow>,意图跟节点一起出现,不再共用一个槽位名。

机制

属性表是一张无序的键值表,键之间没有空间关系。人读属性时,只能靠命名约定重建「谁挨着谁」。拼装把空间关系写回树:子节点的种类和顺序就是结构。编译器和编辑器也能看见这棵树,补全给出的是合法子组件,而不是一份无限延伸的布尔清单。

传参便宜的一面是调用短。短的代价是冲突:新产品要在「标题右侧」放东西,属性表里往往已有一个含义模糊的 extra,于是再叠 extraRightheaderAddon。每个新键都是一次对旧键的重新解释。拼装让新产品加一个子组件类型,旧调用不必重新理解旧键。结构从「猜键名」变成「看树上有没有这块」。

边界

结构本身只有一两处开关、且开关语义封闭时,传参更清楚——按钮的 disabled 不值得做成 <Button.Disabled>。动画、纯样式钩子没有可拼的子角色。服务端只输出属性字典、没有组件树的通道上,拼装无法落地。子组件数量涨到与页面区块一一对应时,拼装已经滑成了把页面拆进库,那是边界划错,不是拼装本身的优点。

怎么落地

  • 把「位置」做成子组件(Dialog.TitleDialog.Actions),把「值」留成属性(文案字符串、选中 id)。位置用拼装表达,值用传参表达。
  • 审查现有属性表:凡是一个键能被两个产品经理解释成两件事的,拆成两个子组件,删掉这个键。
  • 在编辑器补全里只暴露合法子组件,不把内部实现组件放到同一补全面板。
  • 验证:把一处真实调用的全部属性名涂黑,只留标记树。没看过文档的人若能指出哪块是标题、哪块是动作,拼装成立。若必须去翻属性默认值才能知道画面上有没有顶栏,说明结构还埋在参数里。再并列写出传参版与拼装版同一界面:数一数有多少个键需要口头解释,那个数字就是歧义存量。

延伸

  • 同组R1.11.1 插槽把内容的决定权交还给使用方 · R1.11.3 合法的父子搭配需要显式约束 · R1.11.4 上下文传递让子组件适配所处容器
  • 相邻R1.02 组件库与变体 · R1.08 过度抽象
  • 站内检索assembly over props · compound component · composition API

同组卡片

快捷操作

分享

分享当前页面

ios_share

https://hci.top/zh/handbook/R1.11.2