上下文传递让子组件适配所处容器
别名: 容器上下文 · 上下文下发 · container context · context provider
概念解释
上下文传递(component context propagation)让祖先把「你正处在什么容器里」沿组件树向下送,后代读到后改变自己的尺寸、间距、分割线和键盘范围,而不要求每一层把这些值再开成属性往下传。工具栏里的按钮变紧凑,表格行里的选择器变矮,表单字段组里的标签改成顶对齐——子组件适配的是所处容器,不是调用点逐一手写的尺寸参数。
它解决的是「我在哪」,不是「我是谁的合法孩子」。孩子已经合法地坐在父级里;上下文告诉它父级此刻的环境:密度、方向、表面角色、是否在溢出折叠中。
机制
容器的环境值若靠属性逐层转发,中间每一层都必须认识这些属性,即使中间层自己不用。漏传一层,深处的控件就回到默认外观,和邻居不再一套。属性表还会在中间层与局部覆盖撞名:到底是工具栏的紧凑,还是这一颗按钮自己的紧凑,阅读代码的人分不清。
上下文把环境做成树的隐式参数:提供者在容器根上写一次,消费者在叶子上读。中间层可以透明,不必声明自己不关心的键。覆盖发生在更近的提供者,距离规则清晰。子组件因此能在不同容器里换一套度量,而对外接口仍是同一角色——按钮还是按钮,只是读到了「我在工具栏里」。
边界
跨文档、跨 iframe、跨门户的树会切断上下文,子组件读到的是缺省值,必须在边界上显式再提供一次。读上下文的组件被渲染到「没有容器」的故事书孤岛上,会画出一种产品里从不出现的默认体量,预览因此不可信。把品牌色、主题轴也塞进同一条组件上下文,会把「我在哪个容器」和「我在哪套皮肤里」缠成一团,后者有自己的替换层。需要调用点明确覆盖的局部例外(这一颗按钮偏大),应走属性而不是再开一条平行上下文,否则两套来源会互相踩。
怎么落地
- 列出容器要下发的环境:密度、方向、表面、是否折叠。每个值写清缺省以及谁有权覆盖。
- 在容器根提供上下文,在叶子读取;中间布局组件默认透传,不把环境拆开成自己的属性再往下递。
- 为「无容器」的孤立渲染提供测试用提供者,避免故事书里的默认体量混进产品截图。
- 验证:把同一颗按钮分别放进工具栏、表格单元格、表单行,不给它任何尺寸属性。三处的高度、内边距、图标尺寸应随容器改变。再在中间插入一层不认识这些环境的布局组件,三处表现应保持不变——变了就是漏传。最后在一颗按钮上用属性做局部放大:只这一颗变,邻居仍跟容器走。