持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情
话说自从React/Vue火起来后,无论是话题还是招聘,铺天盖地都是它们,好像只要精通了它们那就是妥妥的高级前端。这里我要炮打司令部:UI框架不是耶稣、不是救世主,太依赖它们反而会毁了你...
毁了你的视野
这些UI框架好似一道道高墙,把你软禁它们温暖的生态圈内,久了你也忘了外面还有广阔的世界。把UI层当作软件的全部,其它都成了附属品。
不需要状态管理、不需要MVC,不需要分层而治、不面向内聚解耦、不思考架构思想,一切都是Component、Hooks。
毁了你的技术
自从有了React/Vue,原生Dom操作就忘了,浏览器渲染原理也懒得学习了,JQ、RX等曾经的经典之作也无人知晓了,设计模式啥的好像也不上了。
你的技术栈就是UI框架的周边生态,离开React/Vue也不知道怎么写前端页面了...
毁了你的状态管理
有了Hooks/CompositionAPI就不需要单独的状态管理了?纯技术上来说或许是可以,但有没有想过Hooks/CompositionAPI都是特定UI框架的产物,与UI框架的渲染、生命周期深度耦合。 在JS国度中它们就像各种方言,再加上一些隐晦的心智负担,远没有一个Flux框架条理简单清晰。
而且,测试、监控、回滚一个“Action”多容易,你测试、监控、回滚一个“Hooks”试试...
当然并不是说Hooks就不好,不能用了。Hooks属于UI自己的魔术方法,让它处理自己份内事情当然得心应手,而其它非UI职责的事情,虽然它也可以干,但不合适。术有专攻,能说普通话为啥要用方言?
毁了你的工程
兄弟们打开你们的Component代码看看,是不是充斥着各种生命周期、各种数据定义、各种交互逻辑、各种业务逻辑、各种Ajax请求、各种路由跳转、各种Cookies/LocationStorage操作等等,轻轻松松几百行代码...
不要说有了Hooks/CompositionAPI就可以拆解了、就清晰了,No,只是可以更小粒度复用了,但可能变得更不直观了。
某些简单的数据交流,需要被Props传来传去,即便是我不需要,也要为我的儿孙代传,还要考虑传递和接收是同步还是异步、会不会出现闭包陷阱,会不会导致冗余渲染...好好的一条直路,被UI框架的渲染机制给带偏了。
将UI框架拉下神坛
UI层不是软件架构的全部,甚至连核心都不是,UI的指责只有2个:输入与输出,仅此而已。
它是问题的收集者和结果的反馈者,而不应当成为问题的解决者。
应用的核心是业务逻辑
那应用的核心是什么?是业务逻辑,而非UI交互逻辑。
UI的存在只是让用户更友好的使用系统,就像Dos、Linux系统不安装UI就不能用了吗?
那么现在问你一个问题:
如果你的应用不使用UI,用户可以通过命令来使用吗?
你可能会怼我说,不会有用户通过命令来使用我的应用,这是个没有意义的假设。然而,这种场景或许不是开放给用户使用的,而是给留合作伙伴、留给测试工具、留给日志分析用的呢?
不要过度依赖UI层
- UI说:应用要改版,皮肤、交互、页面组织都要调整,要多久?
- 产品说:把H5改改,做成小程序、APP吧,要多久?
- 经理说:React人太难招了,要不我们换成Vue吧,要多久?
- Leader说:Vue3出来了,我们升级为最新版吧,要多久?
业务逻辑不变,仅调整UI和其运行平台,问你要多久?一个星期?一个月?一年?还是...
同质化的UI框架
把UI框架看得太重?还在纠结使用“React”好还是“Vue”好?纠结“Ajax请求”是放“onCreate()”还是“onMount()”?每天都想着如何优化渲染性能?遇到异己总要去争论哪个更牛B?
试问 VUE3+JSX 与 React 又有多大的差别?
重提软件架构
把UI层变薄,它不过是渲染数据(输出)和收集动作(输入)。
让Controller、Model层回归,它们才是架构的C位,应用的大脑。
重提分层而治、重提MVC,让“客观、稳定”的业务逻辑不被“感性、多变”的UI逻辑干挠,保证核心逻辑可以跨越UI框架、跨越运行平台而运行。
重振Flux框架
MVC如何落地?大名鼎鼎的Flux架构就是一种 Controller 和 Model 的落地方案。
Redux
/Vuex
/Pinia
、已及后面要推荐给大家使用的Elux
,都可以看作它的变种。
从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的处理链条具备“协程”机制,更好的协同各业务动作之间的关联。
基于模型驱动
正是因为遵循了轻UI、重Model
的设计思想,让Elux可以跨框架,可以使用React/Vue/更多其它UI框架
来开发,可以不用为了React而学习NextJS
,为了Vue又学习NuxtJS
,UI框架已经变得没那么重要了。
正式因为分离了UI逻辑和业务逻辑
,让Elux工程可以跨平台,可以用一种工程模式开发Web(浏览器)、Micro(微前端)、SSR(服务器渲染)、MP(小程序)、APP(手机应用)。
此致!欢迎交流:eluxjs.com