组件作为协议
核心理念:组件即协议
这篇文章要回答什么?
Section titled “这篇文章要回答什么?”这一篇不讨论具体 API,也不展开工程实现。
它关注的是更前面的几个问题:
- Proto UI 所理解的“组件”究竟是什么?
- 为什么组件可以脱离某个具体技术实现,被当作一种可描述对象来看待?
- 为什么 Proto UI 会进一步把这种对象视作一种“协议”?
- 为什么 Proto UI 使用
Prototype、Adapter和Host这组命名?
组件并不只存在于代码里
Section titled “组件并不只存在于代码里”在不同技术中,组件会以不同形式出现:
- 一个 class
- 一个 function
- 一个 object
- 一段模板与状态
- 一个可被实例化的图形控件
这些形式都成立,但它们更像是组件的实现形态,而不是组件概念本身的起点。
在 Proto UI 的语境里,组件首先是一个相对稳定的交互单位。
它能够响应输入、产生反馈、暴露能力,并在与外部的关系中保持某种可识别的身份。
因此,Proto UI 关注的重点不是某个框架如何定义组件,而是:
一个对象是否已经构成了可交互、可描述、可被还原的单位。
从这个角度看,组件首先是一种交互主体,代码只是它在特定宿主中的实现方式之一。
组件的预期,往往先于实现而存在
Section titled “组件的预期,往往先于实现而存在”在很多软件协作场景中,组件并不是从代码开始被认识的。
在实现之前,人们通常已经会讨论:
- 它在不同状态下应该如何表现
- 它在交互中应当如何响应
- 它在某些场景下是否“还原”了预期
这些讨论可能来自设计稿、产品原型、交互说明,或者团队内部的约定。
它们未必是代码,却已经足以让人区分:
- 哪些实现更接近预期
- 哪些实现虽然可用,但已经偏离了组件原本的交互身份
“还原度”这个概念本身就说明了一件事:
组件并不完全等同于某段实现代码。
如果组件只等于实现,那么实现之间只存在替换关系,不存在“还原得是否足够好”的判断。
这意味着,组件的某些关键信息,往往在具体实现之前就已经存在,并且能够被人识别和比较。
原型不是漂浮的能力清单
Section titled “原型不是漂浮的能力清单”把组件理解成一种可描述对象,并不意味着 Proto UI 会把原型理解成一组可以任意挂接的零散能力。
在 Proto UI 中,原型始终指向一个会成立的交互主体。
它描述的不是一团抽象规则,而是一个可以在宿主中获得承载、可以在时间中展开、可以与外部发生关系的对象。
因此,一个原型不能失去自己的依附结构。
它至少需要有一个根节点,或者至少有一个不可被摘除的交互依附位置。
这里说的并不是某个具体宿主里的“最外层元素”,
而是一个更高层的要求:
原型必须始终指向“当前这个交互主体自身”,而不是一组漂浮的局部能力。
也正因为如此,Proto UI 才会在后续语法和边界设计里,反复强调“原型作用于自身”这件事。
如果一个对象已经不再拥有自己的依附结构,它也就很难继续被看作一个独立成立的原型。
可抽象,不等于已经成为协议
Section titled “可抽象,不等于已经成为协议”到这里,可以先得到一个比较弱的结论:
组件可以被抽象地理解。
但 Proto UI 关心的不只是抽象本身。
“组件能够被抽象”与“组件能够被当作协议来处理”,是两件不同的事。
前者说明的是:
- 人们可以不依赖具体代码形态去理解组件
后者说明的是:
- 这种理解可以被稳定描述
- 可以在不同实现之间保持较高一致性
- 可以被翻译、维护、约束,并作为公共基建演进
也就是说,抽象强调的是理解方式,协议强调的是稳定性与可传递性。
Proto UI 采取的立场并不是“所有组件天然都是协议”,而是:
组件中存在一部分内容,可以被推进到协议层来理解。
这部分内容通常具有几个特征:
- 不依赖某个单一实现才成立
- 可以被相对稳定地描述
- 可以进入不同宿主而不完全失真
- 可以被长期维护一致性
Proto UI 所说的“原型”,指向的正是这一层。
为什么这里会出现“协议”这个词?
Section titled “为什么这里会出现“协议”这个词?”一旦组件需要进入多个宿主,并在不同实现之间保持相对稳定的交互身份,问题就不再只是“如何描述它”,而是:
- 哪些信息属于组件本身?
- 哪些行为是实现必须尊重的?
- 哪些差异可以接受,哪些差异会破坏一致性?
- 当组件进入不同宿主时,哪些内容需要被翻译,哪些内容不应丢失?
这类问题已经很接近“协议”所处理的范围。
这里的“协议”并不是说组件等同于网络协议或通讯协议,
而是说它开始表现为一种:
可描述、可翻译、可约束的交互契约。
从这个角度看,“组件作为协议”指的不是组件脱离实现而神秘地存在,
而是组件的核心交互语义可以不被某一个实现独占。
Proto UI 为什么使用 Prototype、Adapter 和 Host
Section titled “Proto UI 为什么使用 Prototype、Adapter 和 Host”围绕这层关系,Proto UI 使用了三组核心概念。
Prototype(原型)
Section titled “Prototype(原型)”Prototype 指的是组件中相对稳定、可描述、可复用的交互定义。
它不是某个框架里的最终实现,
而是组件交互身份的一种独立表达。
“原型”这个命名的重点不只是“抽象”,还在于它提供了一种参照:
具体实现可以不同,但它们仍然可以被拿来和同一个原型比较。
同时,这个原型始终描述的是一个会成立的交互主体,
而不是一组可脱离主体存在的局部规则。
Adapter(适配器)
Section titled “Adapter(适配器)”Adapter 指的是将原型翻译到某个具体宿主中的解释层。
它负责的不是重新定义组件,而是处理原型与宿主之间的映射关系,例如:
- 如何承接原型中的交互定义
- 宿主能够直接支持哪些能力
- 哪些部分需要以宿主自己的方式实现
适配器的存在,使“同一个原型进入不同宿主”成为可以被组织和维护的事情。
Host(宿主)
Section titled “Host(宿主)”Host 指的是 Proto UI 的实际落地环境。
它可以是某个前端框架、某个平台、一类 GUI 技术,或者更广义的承载环境。
Proto UI 使用“宿主”这个词,是为了强调一件事:
Proto UI 并不取代这些环境,而是在它们之上落地自己的交互模型。
因此,Proto UI 的目标不是脱离宿主存在,而是在宿主之中维持更稳定的一层交互语义。
三者之间的关系
Section titled “三者之间的关系”如果用最简化的方式来表示,可以写成:
Prototype + Adapter = Host 中的组件实现
这里:
Prototype定义组件的交互主体Adapter负责将它翻译到目标宿主Host提供实际承载能力
这并不意味着所有宿主天然完全等价,
也不意味着任意组件都能零成本迁移。
它表达的只是:
组件中有一部分内容,可以从具体实现中分离出来,作为更高层的交互对象被处理。
Proto UI 的后续模型,基本都建立在这个前提之上。
原型可以开放,协议可以稳定
Section titled “原型可以开放,协议可以稳定”Proto UI 并不要求所有人对组件都得到同一种原型划分。
不同团队、不同产品、不同宿主约束下,对组件边界的理解本来就可能不同。
因此,原型作为概念,本身可以是开放的,也允许出现不一致。
但与此同时,另一件事仍然可以成立:
官方提供的基础原型,可以像协议一样被维护。
也就是说:
- 原型作为一种抽象方式,可以保持开放
- 原型作为公共基建的一部分,可以追求更高一致性
Proto UI 所推动的,并不是唯一正确的组件划分方式,
而是让那些值得稳定下来的公共部分,能够以协议化的方式持续演进。
这一篇没有展开什么?
Section titled “这一篇没有展开什么?”为了保持主线清晰,这一篇不会展开以下内容:
- 原型内部具体包含哪些子能力
- 执行周期、生命周期与相位规则
- 适配器的工程结构
- 某个宿主中的具体落地方式
这些内容会在后续章节中继续讨论。
如果组件要被当作协议来理解,接下来的问题就是:
组件内部哪些部分真正稳定到值得进入这层协议?
这正是下一篇 信息通路模型 要讨论的内容。