【译】MVC 在前端已死?

原文:https://medium.com/@alexnm/is...

随着越来越多的前端开发开勇单项数据流架构,有些人就开始考虑传统的 MVC 是否还有未来?为了便于理解,我们首先分析一下前端架构的发展史。

在过去的 4 年里,我看过许多 web 项目并花了大量的时间在前端架构或是为它整合一些框架。在 2010 年前,JavaScript(实现 jQuery 的语言)在传统 web 应用中被广泛用于 DOM 操作以及添加一些简单的东西。人们并不关心架构方面的东西,一些 简单的模块化方式 似乎已经足够用于设计我们的代码了。

前端架构 vs 后端架构的讨论随着单页应用这个概念的出现而爆发了,随之出现的框架有比如:backboneknockout。由于当时感念也都比较新,所以框架的设计者们不得不去其他地方获取灵感,所以他们借鉴了一些来自后端架构中的实践,而几乎所有的知名后端框架都是传统 MVC 的实现,由于其中的 一些小差异,也可以被叫做 MV*。

当 React.js 第一次以一个 View 层渲染库出现在人们眼前时,它由于将 HTML 和 JavaScript 写到一起的这种非直观方式而被嘲讽。但人们忽视了 React 带来的重要贡献 —— 基于组件架构。React 并没有发明组件的概念,但它让组件开发更进一步。当 Facebook 在介绍 React 时将其称为 “V in the MVC” 时,这一架构上的重大突破甚至连 Facebook 也忽视了。顺便说一句,在 review 完一份 同时使用了 Angular 1.x 和 React 的代码库 后,我直到现在还在做恶梦。

不过在 2015 年,随着 ReduxRxJS 的使用,Flux 和函数式响应式编程(FRP)将我们从习惯上的传统 MVC 的思维模式转变到 单项数据流架构

那 MVC 到底问题在哪里?

当然,MVC 作为一个架构模式已经被开发使用了相当长的时间,同时也可以被使用与 web 开发。不要误会,MVC 现在依然是后端开发中最好的模式,像 Rails 和 Django 等框架都很乐意使用这种模式。

但问题在于,MVC 在后端的使用的原则与分层方法与前端是不同的。

控制器与视图耦合(Controller-View coupling

从下图可以看到视图层和控制器在服务器端是如何交互的,它们仅有两个接触点,都跨越了客户端和服务器端的边界。

当我们将 MVC 放到客户端,这就有问题了。控制器类似与我们所知的 code-behind。控制器是高度依赖视图的(见下图),在一些框架的实现中,它甚至是被视图创建的(比如:ng-controller)。

另外,当你从单一职责原则(SRP)的角度考虑,这显然不满足。客户端的控制器代码同时进行了 事件响应业务逻辑

胖模型(The fat Model)

考虑一下你在客户端存储的是何种模型。一方面我们有一些数据类似于 usersproducts 代表我们的应用状态(Application State)。另一方面,我们需要存储一些 UI 状态,比如 Tab 是否显示(_showTab_)或者当前选中的值(_selectedValue_)。

类似于控制器,模型也在违反单一职责原则(SRP),因为我们没有一个好的办法将 UI 状态和应用状态分开管理。

那什么是适合组件的模型呢?

一个组件就是:视图 + 事件响应 + UI 状态。

下图展示了我们如何真正的将 MVC 的模型分离成组件。然而红线上方的部分,正是 Flux 尝试去解决的:管理 应用状态业务逻辑

随着 React 以及基于组件的架构的流行,我们看到单项数据流在管理应用状态方面的崛起。这两者可以如此方便的配合在一起使用是因为它们完全覆盖了原先的 MVC 的方式,并提供了一个对前端架构而言更好的关注点分离的方案。

不过不久后这就不止 React 了。如果你看过 Angular 2,你会发现它采取了完全相同的模式,不过你也可以用不同的方案来管理应用状态,比如 ngrx/store

现在真的没有能做的更好的了,MVC 在起初就注定失败。我们需要时间来探索,这是一个 5 年的发展过程才将前端架构发展到今天。想想看,5 年其实对一个最佳实践的建立来说不算很长。

MVC 在起初是必要的,因为我们那时不知道在应用越来越庞大和复杂的时候,要如何组织我们的前端应用。我觉得它已经达到了起初的目的,而且也可以学习到,如果是从一个上下文(服务器端)应用到另一个(客户端)的时候,MVC 会是一个最佳实践。

所以,未来将会是什么?

对我们的前端应用来说,我不认为我们会很快回到传统的 MVC 架构。随着也来越多的开发者开始发现组件和单项数据流架构的优势时,关注点会被放在如何基于这条道路建设更好的工具和三方库。

那这类架构回事未来 5 年最好的解决方案吗?很有可能是这样,但是未来没有东西是确定的。5 年前,没有人能预测现在我们是如何写应用的,所以现在我们也不敢这么说。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如果组件之中有复用的代码,需要重新创建一个父类,父类中存储公共代码,返回子类,同时把公用属性...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例如我们的 setState 函数式同步执行的,我们的事件处理直接绑定在了 dom 元素上,这些都跟 re...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom 转为真实 dom 进行挂载。其实函数是组件和类组件也是在这个基础上包裹了一层,一个是调...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使用,可能是不了解。我公司的项目就没有使用,但是在很多三方库中都有使用。本小节我们来学习下如果使用该...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接触 react 就一直使用 mobx 库,上手简单不复杂。
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc 端可以使用分页进行渲染数限制,在移动端可以使用下拉加载更多。但是对于大量的列表渲染,特别像有实时数据...
本小节开始前,我们先答复下一个同学的问题。上一小节发布后,有小伙伴后台来信问到:‘小编你只讲了类组件中怎么使用 ref,那在函数式组件中怎么使用呢?’。确实我们...
上一小节我们了解了固定高度的滚动列表实现,因为是固定高度所以容器总高度和每个元素的 size、offset 很容易得到,这种场景也适合我们常见的大部分场景,例如...
上一小节我们处理了 setState 的批量更新机制,但是我们有两个遗漏点,一个是源码中的 setState 可以传入函数,同时 setState 可以传入第二...
我们知道 react 进行页面渲染或者刷新的时候,会从根节点到子节点全部执行一遍,即使子组件中没有状态的改变,也会执行。这就造成了性能不必要的浪费。之前我们了解...
在平时工作中的某些场景下,你可能想在整个组件树中传递数据,但却不想手动地通过 props 属性在每一层传递属性,contextAPI 应用而生。
楼主最近入职新单位了,恰好新单位使用的技术栈是 react,因为之前一直进行的是 vue2/vue3 和小程序开发,对于这些技术栈实现机制也有一些了解,最少面试...
我们上一节了了解了函数式组件和类组件的处理方式,本质就是处理基于 babel 处理后的 type 类型,最后还是要处理虚拟 dom。本小节我们学习下组件的更新机...
前面几节我们学习了解了 react 的渲染机制和生命周期,本节我们正式进入基本面试必考的核心地带 -- diff 算法,了解如何优化和复用 dom 操作的,还有...
我们在之前已经学习过 react 生命周期,但是在 16 版本中 will 类的生命周期进行了废除,虽然依然可以用,但是需要加上 UNSAFE 开头,表示是不安...
上一小节我们学习了 react 中类组件的优化方式,对于 hooks 为主流的函数式编程,react 也提供了优化方式 memo 方法,本小节我们来了解下它的用...
开源不易,感谢你的支持,❤ star me if you like concent ^_^
hel-micro,模块联邦sdk化,免构建、热更新、工具链无关的微模块方案 ,欢迎关注与了解
本文主题围绕concent的setup和react的五把钩子来展开,既然提到了setup就离不开composition api这个关键词,准确的说setup是由...
ReactsetState的执行是异步还是同步官方文档是这么说的setState()doesnotalwaysimmediatelyupdatethecomponent.Itmaybatchordefertheupdateuntillater.Thismakesreadingthis.staterightaftercallingsetState()apotentialpitfall.Instead,usecom