【论道】组件封装原则

23 阅读4分钟

"把别人还给别人,把自己还给自己。" ——杨绛

人如果一直活在自己对事物的理解而不复盘,终会变得短视固执,最近大量阅读了关于组件二次封装的源码,深有体会,尝试用自己的话去总结,以便提升自己编程能力。

组件库的本质是基于原生或者上级组件库进行多次封装的组件的集合,它在业务中的主要功能是提升开发效率,或者实现需求方提出的特定需求。

在业务中开发其实是命令式的: 这一步做什么,下一步又该做什么,如果有条件,那该做什么,否则就做什么。 而在封装公共组件的过程中则是声明式的: 在数据层面穷举了所有可能而非程序逻辑层面,确保程序逻辑在运行时是以设计预想的进行,确保最差场景下也依然可控。程序不关注(或者尽量少的关注)条件,只是依照在数据层当下映射的数据结果进行渲染。

"元"的中文意思指的是,如同上篇ai篇本质上是元提示给出基础prompt从而让ai生成对应prompt 而这篇的本质则是元编程,即目的是写出用于生成代码的代码。用户在界面上看到的,本质上应是配置数据项在ui层面的必然的、动态的正确映射。。

写到这里突然觉得世间无道,因为所有的道在高一阶的层面也只是特定条件下的应用()而已,最后只会归而为一,这个道则为本身。所谓论道论术本质上也没有区别,一个是描述当下阶段条件的规律,是抽象的,是不可视的;论术指的是当下阶段条件的具体实施办法,是可视的,是具体的,但是本质上也藏着当下具体条件下的事物规律,即当下的道。因而我们说,道是术的规律,术是不同约束下道的实体具现。

如此目标就清晰明了了:开发者编程的目的不再是单纯的为了实现某一业务需求而去编码,而是为了实现某一类需求而编码;不再是为了实现基础需求而编码,而是为了完成生成代码的代码而编码,条件的多变性在数据层,程序逻辑层面也仅仅是为了描述它的当下的的状态,ui也仅仅是为了展示数据当下的状态 [ui = f(state)] 所有的编码活动都是为了上述目的,因而有以下几点原则(也可以称作为约束):

一:声明式架构原则
  1. 配置驱动:组件不具备具体的业务字段,而是通过一套基于当前的,特定的规约来描述视图,
  2. 状态投影:将UI视为状态的函数,所有的状态切换以及数据变化都是数据状态改变后的自然映射,而不是手动操作dom后的结果
  3. 单一事实来源: 所有的业务逻辑[显示,隐藏,校验,默认值]都内聚在配置对象里,目的是避免逻辑在模板和脚本中碎片化分布
二:控制反转与插件化

基础设施必须承认自己的局限性,即无法预知所有需求

  1. 注册表模式:确保在新增需求时仅需增加一个注册项而不必重构整体
  2. 插槽兜底:永远为不可预知的未来需求预留插槽兜底
三:最小惊讶原则

一个程序的组件,其行为方式应该最大程度地符合用户的预期。 衡量一个封装组件是否“好用”的物理标准。

  1. 透明透传:不要试图拦截或重新定义底层 UI 库(如 Element Plus)的原生属性。(vue用户通过 v-bind="props" 直接透传)让开发者能查阅原生文档就直接使用,不制造额外的黑盒。
  2. 契约稳定性: 组件的输入(props)与输出(events)应保持稳定,即便内部逻辑重构,业务代码也不应崩溃[换句话说本质上只是换了表达形式,但是输入与输出形式不应改变]
四:健壮的数据契约

一个通用组件必须具备处理“脏数据”和“非对称需求”的能力。

  1. 非破坏性重置:组件卸载动作不应只是清空,而是应该回归到组件的最初始配置。
  2. 防御性编程
五:逻辑下放与闭环

将业务决策权交给调用者,组件只负责执行决策。

  1. 钩子函数:在联动,回调,校验,转换等关键节点提供回调,让父组件决定如何变化
  2. 在出现更新动作时,组件应能自动处理响应式收集与内存清理,防止残存的数据bug
  3. 在业务方可能需要的地方预先埋点。

或许过程的确痛苦,但配得感终将抚慰内心。

以上。