原型边界
哪些内容应该进入 Prototype,以及原型应如何拆分
这篇文章要回答什么?
Section titled “这篇文章要回答什么?”上一篇讨论了 Proto UI 如何通过信息通路来理解组件。
接下来的问题是:
当一个组件内部包含多个子结构时,哪些内容应该放在同一个原型里,哪些内容必须被拆成独立原型?
这不是一个单纯的工程组织问题。
它关系到 Proto UI 如何理解“一个原型到底在描述谁”。
这一篇要回答的是:
- Proto UI 为什么不能随意拆分或合并原型
- 一个子结构什么时候必须被视为独立原型
- 为什么“是否激活信息通路”会成为原型边界的判断依据
- 为什么这条边界不只是一条建模原则,也会体现在原型语法中
Proto UI 关心的不是切块,而是交互主体
Section titled “Proto UI 关心的不是切块,而是交互主体”如果原型只是视觉树的一种写法,那么拆分原则其实并不重要。
你当然可以:
- 按视觉区域拆
- 按 DOM 层级拆
- 按文件大小拆
- 按作者喜好拆
这些方式在工程上都能成立。
但 Proto UI 里的原型并不是为了描述“画面被切成了几块”,而是为了描述:
谁在承担独立的交互责任。
这意味着,Proto UI 不能把原型理解成任意切分的结构片段。
如果缺少边界原则,原型就会退化成一种更抽象的模板拆块方式,失去它作为“交互主体”的意义。
Proto UI 之所以关心原型拆分,本质上是在关心:
一个子结构是否已经形成了独立的交互责任边界。
原型不能失去自己的依附结构
Section titled “原型不能失去自己的依附结构”Proto UI 中的原型不是一组可以漂浮存在的局部规则。
它必须依附于一个明确的交互结构,才能作为原型成立。
因此,一个原型需要至少拥有一个根节点,
或者至少拥有一个不可被摘除的交互依附结构。
这条约束的意义并不只在结构上。
它保证了原型始终在描述“一个交互主体自身”,而不是一组可以任意挂接到别处的零散能力。
也正因为如此,Proto UI 的原型语法默认总是作用于当前原型自身。
如果一个结构已经脱离了这个根依附关系,
它更可能意味着:这里其实已经需要另一个原型。
一个子结构何时应被视为独立原型?
Section titled “一个子结构何时应被视为独立原型?”Proto UI 采用的核心判断并不复杂:
看这个子结构是否开始承担独立的信息通路责任。
也就是说,判断一个子结构是否仍然只是父原型的一部分,
不能只看它“长得像不像一个局部组件”,而要看它是否已经开始以自己的身份与外部交换信息。
从这个角度看,原型的边界首先不是视觉边界,也不是代码边界,
而是交互责任边界。
Proto UI 的拆分判断
Section titled “Proto UI 的拆分判断”在当前的 Proto UI 中,可以先用下面这组规则理解原型拆分:
1. 当一个子结构存在除 feedback 之外的任一信息通路需求时,它必须拆成独立原型
Section titled “1. 当一个子结构存在除 feedback 之外的任一信息通路需求时,它必须拆成独立原型”这里的“信息通路需求”包括但不限于:
- 它开始响应独立的
event - 它拥有自己独立的
props - 它向外
expose自身能力 - 它订阅或分发
context
一旦这些关系出现,就说明这个子结构不再只是父原型中的一段内部构造。
它已经开始以自己的方式面对用户、使用者或其他组件。
在 Proto UI 看来,这意味着它已经构成了独立的交互主体,因此应当拥有独立原型。
2. 当一个子结构仅激活 feedback 通路时,它可拆可不拆
Section titled “2. 当一个子结构仅激活 feedback 通路时,它可拆可不拆”如果一个子结构只承担 feedback,事情会变得没那么绝对。
这类子结构确实已经在参与组件与用户之间的信息关系,
但它参与的是更接近“呈现与感知”的一层。
它本身并不必然意味着这个结构已经形成了独立的交互责任中心。
因此,Proto UI 允许这里保留一定弹性:
- 可以把它保留在父原型内部
- 也可以为了复用、清晰度或实现便利将其拆出
3. 当一个子结构没有激活任何信息通路时,它必须不拆
Section titled “3. 当一个子结构没有激活任何信息通路时,它必须不拆”如果一个子结构既不接收输入,也不向外反馈,也不承担配置、暴露、协作等关系,
那么它在 Proto UI 中就仍然只是父原型内部的一段结构。
这时如果强行拆分,得到的并不是新的交互主体,
而只是对内部结构做了额外命名。
这类拆分不会增强原型的表达能力,反而会稀释原型的意义。
为什么 feedback-only 可以不拆?
Section titled “为什么 feedback-only 可以不拆?”这是这套原则里最容易让人停下来追问的地方。
如果从更纯粹的逻辑角度看,只要一个子结构激活了任意信息通路,
把它拆成独立原型,其实完全说得通。
因为它确实已经不再是完全静止、完全封闭的内部片段。
但 Proto UI 在这里没有采取最严格的形式化路线。
原因并不复杂:
工程上的可读性,也是原型设计的一部分现实约束。
feedback 这一通路更靠近呈现与感知层。
一个子结构如果只承担 feedback,它确实可能已经具有某种局部意义,
但这种意义未必足够强,未必强到必须被提升为独立原型。
如果在这里一律强制拆分,理论上当然可以得到更细粒度、更一致的形式系统;
但在实践中,它往往会带来另一个问题:
- 原型数量迅速增加
- 每个原型承载的信息量变少
- 人类开发者需要在更多细小单位之间来回切换
- 最终读起来更碎、更难形成稳定的整体理解
换句话说,feedback-only 可拆可不拆,并不是因为它在哲学上完全等同于“未激活通路”,
而是因为 Proto UI 在这里承认了一种现实:
对人类作者和维护者来说,原型不仅要正确,还要可读。
因此,这是一种明确的工程妥协。
它保留了形式系统的主干,同时避免把原型粒度推到对人类过于细碎的程度。
一旦独立通路出现,拆分就不再是风格问题
Section titled “一旦独立通路出现,拆分就不再是风格问题”与 feedback-only 不同,其他通路一旦出现,拆分就不再只是偏好选择。
子结构响应独立 event
Section titled “子结构响应独立 event”如果一个局部结构开始独立接收输入,
它就已经不只是“被显示出来”,而是在参与交互决策。
这意味着它正在形成自己的用户通路。
继续把它完全埋在父原型内部,会让父原型承担过多局部交互责任,边界开始变得混乱。
子结构拥有独立 props
Section titled “子结构拥有独立 props”当一个子结构需要被独立配置,它就已经不仅是父结构的内部细节,
而是变成了一个可被上层明确控制的对象。
此时它与 Maker 的关系已经独立成立,
Proto UI 会认为它应当拥有自己的原型边界。
子结构向外 expose 状态或方法
Section titled “子结构向外 expose 状态或方法”如果一个子结构开始主动向外暴露能力,
那它已经不再只是父原型内部的一段实现,而是在以自身身份参与更大的交互系统。
这类边界一旦出现,继续把它视为纯内部结构,通常会让原型职责发生混叠。
子结构订阅或分发 context
Section titled “子结构订阅或分发 context”当一个子结构开始感知和参与组件网络中的环境关系,
它就已经进入了另一条独立的信息通路。
这时它承担的已经不是局部渲染责任,而是某种组件间协作责任。
Proto UI 会把这视为足够明确的独立原型信号。
Proto UI 如何强制原型边界成立
Section titled “Proto UI 如何强制原型边界成立”在 Proto UI 中,原型边界并不只是一个建模建议。
它还会直接体现在语法设计里。
对于一个仍然留在父原型内部的子结构,Proto UI 默认并不给作者提供这样的能力:
- 单独给它设置
props - 单独给它绑定
event - 单独让它
expose能力 - 单独让它参与
context关系
也就是说,Proto UI 不支持作者在“还没有把子结构拆成独立原型”的前提下,
先偷偷让它承担第二套信息通路责任。
这使得原型拆分不是一种事后整理风格,
而是在语法层就被提前约束的边界判断。
这里唯一保留弹性的,是 feedback-only 的情况。
如果一个子结构只承担 feedback,Proto UI 允许它继续留在父原型内部。
但只要它开始承担其他信息通路责任,拆分就不再是可选项。
这条限制还会反过来影响原型作者的写法。
由于 Proto UI 默认不提供原型级别的结构组合,
作者也无法预设某个子结构未来会以怎样的方式与其他原型拼接。
在这种前提下,更自然的写法通常是:
把交互状态与交互责任尽量收敛到当前原型自身,
而不是把控制权预先交给一个尚未成立的外部原型。
从这个角度看,Proto UI 的原型边界并不是只靠概念说明来维持,
而是通过语法能力的有意缺失,被直接固定在写作过程中。
拆分之后,组合回到宿主侧
Section titled “拆分之后,组合回到宿主侧”Proto UI 要求子结构在激活独立信息通路后被拆成原型,
但这些原型之间的最终组合,并不在 Proto UI 默认主轴中完成。
Proto UI 允许原型层发生逻辑复用,
例如把另一段原型逻辑融入当前原型中。
这更接近继承或 hook 调用,处理的是逻辑复用,而不是最终 UI 的结构组合。
而多个独立原型如何拼接成最终界面、如何进入业务接合层、如何参与更复杂的场景调度,
这些事情默认回到宿主侧处理。
也正因为如此,Proto UI 在这里强调的不是“如何把结构拼起来”,
而是“哪些东西已经必须先被识别为独立原型”。
原型拆分不是为了追求“越细越好”
Section titled “原型拆分不是为了追求“越细越好””看到这里,一个常见误解会自然出现:
既然 Proto UI 这么强调边界,那是不是原型拆得越细越好?
答案是否定的。
Proto UI 的目标不是把组件不断切成更小的单位,
而是让每一个原型都尽可能对应一个清晰的交互主体。
拆分过少,会让多个责任被混在一起;
拆分过多,则会让原型失去可读性,退化成形式上的微粒化描述。
因此,Proto UI 追求的不是“最小原型”,而是:
交互责任边界清晰,同时仍然适合人类理解的原型粒度。
这也是为什么信息通路会成为判断依据。
因为它比视觉树、模板层级或实现风格更接近“这个结构是否真的在独立承担交互责任”。
原型边界的真正含义
Section titled “原型边界的真正含义”在 Proto UI 中,一个独立原型并不只是“可以被单独命名”的结构。
它意味着更具体的一件事:
这个对象已经拥有了独立的交互责任边界。
它需要被单独描述,
不是因为作者想把代码拆开,
而是因为它已经开始作为自己的交互主体存在。
从这个角度看,原型边界其实是在回答:
- 这个责任究竟属于谁
- 这条信息通路究竟由谁承担
- 哪些交互应该被视为父原型内部细节,哪些已经应当被独立建模
这也是 Proto UI 反复强调原型边界的原因。
没有这条边界,原型就会在“交互主体”和“任意结构片段”之间来回滑动。
这一篇没有展开什么?
Section titled “这一篇没有展开什么?”为了保持主线清晰,这一篇不会继续展开:
- 每条信息通路的正式契约
- 原型 API 的具体写法
- 拆分后的原型如何被适配器消费
- 在不同宿主里,拆分后的语义如何被保持一致
- 宿主侧如何承担最终组合与业务接合
这些问题会在后续章节中继续讨论。
如果原型边界已经被确定,接下来的问题就不再是:
哪些内容应该拆开?
而是:
这些已经被识别出的原型与能力,如何在时间与执行过程中保持稳定秩序?
这正是下一篇 执行语义 要讨论的问题。