为什么在 web 前端很少有人会提到分层架构,例如经典 MVC 架构
,这是因为浏览器诞生之初就只是作为一个后端数据的 GUI 渲染器。也就是说整体来看,web1.0 时代的整个 web 前端工程就是一个 View 层,而Model
和Controller
就是指后端,所以基本无需在 web 前端工程中去提什么 MVC。
然而 web 生态倒退到明天,浏览器越来越弱小,赋能越来越多,甚至不亚于一个小型操作系统,这时候的 Web 前端早已不是当初简略的数据渲染器,随着 PWA、小程序、快利用的推广,WebAPP 曾经和传统的“富客户端”没什么两样了。那么在这种趋势下,如果咱们的 Web 前端架构还停留在 View 的时代,那么显然是掉队的。
View 是最直观的、最原始的驱动源,解决了所有 View 的问题也就实现了 WebApp 的所有性能,前端开发人员的全副工作就是一个又一个的编写Component
。正是因为这种以 View 为外围的架构思维,导致咱们只为解决表层问题而架构,不去思考顶层设计,这也是很多 Web 前端工程通过几轮迭代和人员转手后,很难持续保护上来的根本原因。
近年来涌现出一些优良的 UI 渲染框架,比方 React/Vue/Anglar
,它们很弱小,能够干很多分内和分内的事件。正因为如此,更造成了开发者的惰性,将所有逻辑都间接以最原始的形式写在 View 中,不论是Mode
还是 Controller
,不论是业务逻辑、还是渲染逻辑、还是存储逻辑、还是通信逻辑、还是路由逻辑 … 所有各类逻辑叠加各种 UI 生命周期,全副都耦合在一个Component
中。
从视图驱动到畛域驱动
是时候扭转咱们的架构思维,从 视图驱动
升华到 畛域驱动
。尽管 视图驱动
是最直观也是最简略的一种架构模式,然而咱们不仅要解决问题,还要思考如何优雅的解决问题,这也好比是 排版
和设计
的区别吧!
或者说,在我的项目横蛮成长的混沌初期你能够从下往上构建,所建即所得。但到了某个重构的工夫点,你还是得站在顶部进行下层设计。
当然,这里有个默认前提,那就是须要长期保护的中大型项目,小而快的我的项目无需谈各种架构模式 …
将 UI 框架拉下神坛
UI 不是工程的全副,UI 的指摘只有 2 个:输出与输入 ,仅此而已。所以即使React/Vue
再弱小,你也该当仅把它们当成一个 GUI 工具,相似于 Java Swing
和.Net WPF
,而非整个工程 React/Vue
一把梭。
~~ 敲黑板:UI 只是指令的收集者、传播者、反馈者,而不该当成为指令的执行者。
利用的外围是业务逻辑
当初问你一个问题:
如果没有 UI,你的利用能够通过命令来驱动吗?
你可能会怼我说,用户怎么可能会通过命令来应用我的利用,没有这样的业务场景,你这个假如是毫无意义的。然而,这种场景或者并不是为用户而设,而是为合作伙伴而设、为测试工具而设、为日志剖析而设、为今后的扩大和生态建设而设 …
再问你一个问题:
- UI 说:利用要改版,皮肤、交互、页面组织都要调整,要多久?
- 产品说:把 H5 改改,做成小程序、APP 吧,要多久?
- 经理说:React 人太难招了,要不咱们换成 Vue 吧,要多久?
- Leader 说:Vue3 进去了,咱们降级为最新版吧,要多久?
- 架构师说:Svelte 快到飞,咱们重构为 Svelte 吧,要多久?
业务逻辑不变,仅调整 UI 和其运行平台,问你要多久?这个时候,如果你的全副逻辑都是耦合在某种特定的 UI 框架中的,那你只能是哀默之心大于死 …
UI 逻辑与业务逻辑拆散
从晚期的前后端一体化,到前面的 前后端逻辑拆散
,在到这里我重提UI 逻辑与业务逻辑拆散
,都只是顺着 2 件事件在做:让须要 内聚 的更内聚,让能够 解耦 的更涣散。
- 业务逻辑形象,UI 逻辑具体:业务逻辑是形象的数据模型,而 UI 逻辑则是形象事物逐层泛化后的具体表现,它们两个自身就不再同一个 Level 上。
- 业务逻辑通用,UI 逻辑非凡:UI 逻辑通常须要借助于某个具体的 UI 框架而表白,而 UI 框架通常都会与运行平台非亲非故,同时也会退出本人的各种各种限度、束缚、约定、魔术办法等。所以形象来说,前者是 JS 国家的普通话,而后者则是方言。
- 业务逻辑直观,UI 逻辑费解 :UI 渲染自身就是一件很简单的事件,其间波及到各种组件的各种生命周期、创立、销毁、更新、重绘等等、在加上各种优化伎俩造成的心智累赘。所以你会发现某些业务逻辑放在
Redux
或是Vuex
等纯状态治理框架中,比应用组件外部的 Hooks 去保护更简略和直观。只管 Hooks 也能够模仿这些 Flux 框架,然而不迭前者有条理,比方测试、监控、剖析、回滚一个Action
多容易,你测试、监控、剖析、回滚一个Hooks
试试 … - 业务逻辑稳固、UI 逻辑多变:UI/UE 太理性、太灵便了,带有很强的集体主观色调,常常会被优化、批改、甚至颠覆,不像业务逻辑那么稳固。这也是要将 UI 逻辑和业务逻辑离开的重要起因,如果你将业务逻辑和 UI 逻辑写在一起,你原本稳固的代码将受到不稳固代码的重大骚挠。
铁打的 MV 流水的 C
当初提 MVC 是不是过期了?非也,MVC 是其实一种最简略的哲学思想,Model
代表形象事物,View
代表具体事物,而 Controller
则是代表如何在形象事物和具体事物之间泛化。所以 MVC 是一种思维,而不是特指某种框架,过期的只会是框架,而非思维。
近年来各种演变如:MVP
、MVVM
、MVI
等等,其实都是在围绕 C
做文章,最终的目标无非就是更好的隔离 M
和V
,也就是千方百计拆散 UI 逻辑
和业务逻辑
。
Flux 架构其实也是一种 MVC,而 Redux
/Vuex
/Pinia
、以及自己的框架Elux
,都能够看作它的变种。上面咱们就看看如何利用Flux
架构来拆散 UI 逻辑与业务逻辑:
从 State 到 Model
MVVM 利用中充斥着状态,有的用来形容 Component 的外部情况,它与 Component 唇齿相依,追随 Component 诞生和销毁,这就是咱们常说的 ComponentState
。\
还有一些状态,用来形容业务状态,与具体哪个 Component 没有间接关系,不存在复用与销毁,咱们能够称它为Model
。
- ComponentState 是 UI 逻辑,该当封装在 Component 外面,外界也无需晓得。
- Model 是业务逻辑,反映整个 APP 的情况,与 Component 无关,该当由 Flux 框架来对立治理。
从 Event 到 Action
用户通过 UI 界面产生的人机交互事件,咱们习惯叫 ”Event 事件 ”,而 ”Event 事件 ” 背地的业务目标咱们能够叫 ”Action 动作 ”,它们一个是因一个是果,一个是表一个本。
- 解决 Event 的 Handler 是 UI 逻辑,该当写在 UI 组件中
- 解决 Action 的 Handler 是业务逻辑,该当写在 Controller 外面
举个具体的例子吧:”SubmitLoginForm|提交登录表单 ”,通常要实现如下逻辑:
- 验证输出是否无效
- 验证以后用户是否曾经登录
- 申请后端 API,并期待返回
- 如果胜利,保留用户信息,并跳回原页面
- 如果失败,提醒谬误,并留在原地
这是一个业务动作,因为它能够不依赖哪个具体 UI 而运行,用户可能通过“onClick 事件”点击登录按钮来触发,也可能通过“onKeyPress”按下回车键来触发,甚至你能够间接让用户通过“Login 命令”来触发。
所以“onSubmitLoginForm()”该当写在 Controller
而非 UI 组件中。\
UI 组件中只有 ”onLoginButtonClick()” 或 ”onEnterKeyPress()”,而它们往往也就一句话,就是 Dispatch 一个 Action 来触发 Controller
中的“onSubmitLoginForm()”
将业务逻辑移出 UI 组件,这样 UI 层就变薄了,回归到了它的实质:只负责收集业务动作,不负责解决它。
改进 Flux 框架
传统的 Flux 框架也有痛点:
- 全局中心化治理导致逻辑过于集中;
- 单实例、不销毁容易造成信息累积爆炸;
- DispatchAction 机制过于简略,不适宜解决前因后果的长流程业务。
Elux 正是针对以上痛点进行了改进:
- 尽管保持全局中心化治理,但 Elux 提出“微模块”的概念,将利用拆分成独立自治的一个个“微模块”,每个微模块仅解决本人畛域内的事件。
- 不再单实例,每次路由变动都会产生一个新的空白 Store,而后从新筛选有用的状态挂载,相似一种垃圾回收机制。
- 提出了 ActionBus 的概念,让 Action 作为 Model 中的事件来播送。
- 让 Action 的解决链条具备“协程”机制,更好的协同各业务动作之间的关联。
Elux 践行的分层而治
正是因为遵循了 轻 UI、重 Model
的设计思维,让 Elux 能够挂接 React/Vue
等各种不同的 UI 框架,它们曾经变得没那么重要了。
正式因为拆散了UI 逻辑和业务逻辑
,让 Elux 能够用一种工程模式开发 Web(浏览器)、Micro(微前端)、SSR(服务器渲染)、MP(小程序)、APP(手机利用)。
此致!欢送交换:https://eluxjs.com
最初也想跟大家交换一下 前端“微模块”
的话题:从 ” 微前端 ” 到“微模块”