想写好前端,先练好内功
《笑傲江湖》里封不平剑招再快,没有内力也撑不住。前端同样:React、Vue、Redux、RN、Weex 像各门招式,真正能选型和扛复杂度的,是招式背后的工程思想。
文档还没看完又出新框架,先别慌。框架是手段;开闭原则、函数式编程、消息机制这三套「内功」在后端很常见,前端框架里也在用。下面结合例子把这三件事说清楚。
一、开闭原则
提到面向对象,很多人先想到 23 种设计模式。模式是实践,上面还有 SOLID:
-
Single Responsibility Principle 单一责任原则 -
The Open Closed Principle 开放封闭原则 -
The Liskov Substitution Principle 里氏替换原则 -
The Dependency Inversion Principle 依赖倒置原则 -
The Interface Segregation Principle 接口分离原则
出发点都是「高内聚、低耦合」。后端用得最多的往往是依赖倒置,相关模式大约五六个:
上图也可以看成从抽象到具体的演进。前端框架里用得更多的是开放封闭原则:A software artifact should be open for extension but closed for modification。
翻译:对扩展开放,对修改封闭。看一个面积计算的例子:
场景再扩展,Area 汇总函数也不用改;每种 Shape 自己实现面积。核心逻辑不要轻易动,否则稳定性和测试成本都会炸。应当先抽象、统一接口,扩展时加实体类。
前端里,Ant Design 的 Form 就是开闭原则:它不像普通控件有固定长相,更像容器,提供接入标准和校验、提交。一项可以这样画:
库里已有 Select、Checkbox、Radio、Cascader 等,业务仍会做自定义表单项。Form 约定三条即可接入:
-
提供受控属性 value,或与valuePropName同名的属性。 -
提供 onChange,或与trigger同名的事件。 -
不能是函数式组件。
校验、提交封在 Form 里不变;自定义控件满足约定就能和官方控件一起用。这就是开闭:核心封闭,扩展走接口。
二、函数式编程
交互越来越复杂,FP 凭复用、好测、代码更短,成了很多框架的设计准则。特征大致是:
-
函数为「一等公民」 -
模块化、组合 -
引用透明 -
避免状态改变 -
避免共享状态
JS 函数可当参数和返回值,天生是一等公民。后面四条要靠写法落地。
找出字符串中率先出现的四个非数字字符
非 FP:
FP:
用 filter、slice 拿掉 for,更顺。原文 FP 示例写成了 /[1-9]+/,会把 0 当成非数字留下,和题意「非数字」不一致,这里按 [0-9] 对齐。业务里最常用的是模块化组合。
数组元素相加、相乘、相与
非 FP:每种运算复制一份循环。
FP:运算抽成模块,循环用 reduce:
新运算只需在 ops 里加一项。复杂逻辑切小块再组合,复用往往比 OOD 更顺手。拆太细文件和沟通成本会涨,这是实践里常被抱怨的点。
React 里的 FP
用户操作或接口改数据后,React 做 virtual DOM diff,得到修改指令再打到真实 DOM:
UI 是数据的映射,可以写成 UI = React(data)。
React 的本质是一种函数,而且接近「引用透明」:输出只看参数,不看外部环境。这样好测、好组合。组件由更小组件构成,高阶组件就是透明函数的组合。
三、消息机制
观察者模式、Windows 消息、Spring ApplicationListener、Objective-C 的方法调用,都靠消息驱动。好处是模块解耦,彼此只发消息。
没有消息时,预定系统里用户要知道订单、订单要知道支付,模块互相调用:

改成消息后,下单、支付、预定都发给消息处理器,同时听回来的消息。模块不知道对方存在:
前端里常用 EventEmitter。同一页一块 React、一块 D3,要同步数据就可以走消息。不同生命周期的组件用消息管,耦合下去、关系代码收到一个文件,内聚上来。
消息还带出中间件:通用逻辑放中间件,业务更短。前端里最典型的是 Redux:交互先变成 action,经 reducer 和 middleware 改数据,再同步 UI:
Redux 的利弊社区讨论很多,这里不展开。
| 内功 | 一句话 | 前端落点 |
|---|---|---|
| 开闭原则 | 核心别改,扩展走接口 | Ant Design Form 的 value / onChange 约定 |
| 函数式 | 小函数组合,引用透明 | React:UI = f(data);reduce / 高阶组件 |
| 消息机制 | 模块只发消息、不互调 | EventEmitter;Redux 的 action |
四、参考
-
Functional Programming in JavaScript — Dan Mantyla -
Functional JavaScript: Introducing Functional Programming with Underscore.js — Michael Fogus -
Clean Architecture — Robert C. Martin -
https://reactjs.org -
https://ant-design.gitee.io/docs/react/introduce-cn -
https://redux.js.org/ -
https://redux-saga.js.org/ -
《笑傲江湖》— 金庸 -
《天龙八部》— 金庸 原文链接:https://www.yuque.com/es2049/blog
一句话总结:招式会过时,开闭、函数式、消息这三套内功能帮你看懂框架为什么这么设计,选型才有依据。
转载请注明来源:想写好前端,先练好内功











