为什么很少有人提到web前端的分层架构,比如经典的MVC架构,因为浏览器当时只是作为后端使用其诞生之初用于数据的GUI渲染器。也就是说,整体来说web1.0时代整个web前端项目就是一个View层,而Model和Controller指的是后端,web前端就不用提MVC了——结束项目。但是,在网络生态发达的今天,浏览器的功能越来越强大,能力越来越强,甚至不亚于一个小型的操作系统。这时候,Web前端不再是简单的数据渲染器。、快应用的推广,WebAPP与传统的“富客户端”无异。那么在这种趋势下,如果我们的web前端架构还停留在View时代,显然已经落伍了。View是最直观最原始的驱动源。解决了View的所有问题也就实现了WebApp的所有功能。前端开发者的全部工作就是一个接一个的编写Components。正是因为这种以View为核心的架构思维,我们只构建解决表面问题,不去思考顶层设计。这也是很多前端web项目在几轮迭代和人员变动之后,很难继续维护下去的。根本原因。近几年出现了一些优秀的UI渲染框架,比如React/Vue/Anglar,功能非常强大,可以做很多内部和外部的事情。正因如此,开发者偷懒,所有的逻辑都直接用最原始的方式写在View中,无论是Mode还是Controller,无论是业务逻辑,渲染逻辑,存储逻辑,还是通信逻辑,还是路由逻辑……都是各种逻辑叠加各种UI生命周期,都耦合在一个Component中。从视图驱动到领域驱动,是时候改变我们的架构思维了,从视图驱动升华到领域驱动。虽然视图驱动是最直观、最简单的架构模式,但我们不仅要解决问题,还要思考如何优雅地解决问题。这就像排版和设计之间的区别!换句话说,在项目野蛮生长的混乱前期,可以自下而上地构建,所构建的就是所得到的。但是在重构的某个时间点,还是要站在最顶端进行上层设计。当然,这里有一个默认的前提,就是需要长期维护的中大型项目。小而快的项目不用讲各种架构模型……把UI框架从神坛UI上拉下来不是整个项目,对UI的指责也只有2个:输入输出,仅此而已。所以无论React/Vue多么强大,你都应该只把它们当成一个GUI工具,类似于JavaSwing和.NetWPF,而不是整个项目React/Vue。~~敲黑板:UI只是指令的收集者、传播者、反馈者,不应该是指令的执行者。应用程序的核心是业务逻辑。现在我问你一个问题:如果没有UI,你的应用能不能用命令来驱动?你可能会问我,用户如何通过命令来使用我的应用程序?没有这样的业务场景,你的假设就没有意义。但是,这个场景可能不是为用户设置的,而是为合作伙伴、测试工具、日志分析、未来扩展和生态建设……再问你一个问题:UI说:应用需要改版,皮肤、交互和页面组织必须进行调整。它需要多长时间?产品说:修改H5做成小程序或APP需要多长时间?经理说:React的人太难招了,不如改用Vue吧,要多久啊?leader说:vue3出来了,我们升级到最新版本吧,要多久?架构师说:Svelte要飞了,我们重构到Svelte,要多久?业务逻辑不变,只是调整UI及其运行平台,需要多长时间?这时候,如果你所有的逻辑都耦合在一个特定的UI框架中,那你只能哀莫大伤了……UI逻辑和业务逻辑的分离,已经从早期的前端集成变成了前端分离-后端和后端逻辑在后面,这里我重温一下UI逻辑和业务逻辑的分离,它只是沿着两件事来做的:把需要内聚的更内聚,让可以解耦的更松散。业务逻辑是抽象的,UI逻辑是具体的:业务逻辑是抽象的数据模型,而UI逻辑是抽象事物层层概括后的具体表现,两者本身已经不在一个层次上。通用的业务逻辑,特殊的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到ModelMVVM应用程序中充满了状态,其中一些状态用于描述Components的内部情况,这些状态与Components密切相关并遵循组件的诞生和销毁。这就是我们常说的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”按下回车键来触发它,甚至让用户通过“登录命令”直接触发。所以“onSubmitLoginForm()”应该写在Controller而不是UI组件中。\UI组件中只有“onLoginButtonClick()”或“onEnterKeyPress()”,而且往往只有一句话,即DispatchanAction触发Controller中的“onSubmitLoginForm()”,将业务逻辑移出UI组件化,让UI层变得更薄,回归本质:只负责收集业务动作,不负责处理。改进的Flux框架传统的Flux框架也有痛点:全局集中管理导致逻辑过于集中;单实例,不销毁,容易造成信息堆积爆炸;DispatchAction机制过于简单,不适合长期存在因果关系的业务流程。针对以上痛点,Elux做了改进:虽然坚持全局集中管理,但Elux提出了“微模块”的概念,将应用拆分成独立自主的“微模块”。每个微模块只处理自己领域内部的东西。不再是单一实例,每次路由变化都会生成一个新的空白Store,然后重新选择有用的状态挂载,类似于垃圾回收机制。提出了ActionBus的概念,使得Action在Model中可以作为一个事件进行广播。让Action处理链拥有“协程”机制,更好的协调各个业务Action之间的关系。Elux所践行的分层和规则,正是因为遵循了轻UI重Model的设计思路,使得Elux可以对接React/Vue等各种UI框架,变得不那么重要了。形式上因为UI逻辑和业务逻辑分离,Elux可以用工程模型开发Web(浏览器)、Micro(微前端)、SSR(服务端渲染)、MP(小程序)、APP(移动应用)。此致!欢迎交流:https://eluxjs.com最后跟大家分享一下前端“微模块”的话题:从“微前端”到“微模块”
