reactjs 为什么React不被认为是MVC?

e4yzc0pl  于 2023-02-04  发布在  React
关注(0)|答案(3)|浏览(323)

我知道ReactJS不被认为是MVC,因为它的创建者自己也这么说过。但是,最近有人问我为什么React它不被认为是MVC,尽管它符合MVC模式。React呈现一个视图,当使用客户端的人做出改变时,React会考虑到这个改变,如果需要的话更新状态(状态不只是模型吗?),然后返回更新的视图(就像控制器一样)。我对MVC架构的严格定义有一个非常基本的理解,并且非常困惑为什么React现在不是MVC。

rsaldnfx

rsaldnfx1#

React既不是MVC也不是非MVC。它是一个渲染视图的库(有很多很酷的东西,但仍然)。你可以使用MVC模式,或者Flux/Redux,或者其他任何东西。
MVC和Flux的区别在于后者实现了单向数据流,所以你的数据只能单向移动。您可以从视图和控制器更改模型。

d8tt03nd

d8tt03nd2#

React不 * 视为 * MVC

React不被认为是MVC,因为它与MVC在后端的构思和使用方式没有很好的对应。
React是一个渲染库,理想情况下只负责视图层,它没有一个集中的编排器/路由器,也没有后端MVC架构通常拥有的完全独立(REST风格)的控制器。
由于Facebook错误地将Flux与MVC进行了对比
在描述现有方法的转变时,Flux体系结构与MVC形成了对比(阅读FacebookMVC Does Not Scale, Use Flux Instead)。
但是Flux本身并不直接反对MVC,而是反对可变性和双向数据绑定,MVC并没有指定这两个方面(it even says视图只是"呈现模型的表示")。
您可能会认为Flux架构只是重新构建了MVC,将Model-View-Controller重命名为Store-View-Dispatcher ......重要的区别不是架构实体本身,也不是它们的名称,而是 * 如何限制它们 * Flux不允许双向数据绑定,而人们在使用MVC时经常允许这种绑定**,即makes debugging easier(只需跟踪React树,而不是在组件之间来回,在易变性的情况下:您还必须跟踪到前面使用该值的每个组件),并避免了一些性能问题,如级联状态更改(在模型和视图之间来回跳跃,具有微妙的计时问题),人们在使用双向(又名2-way,双向)数据绑定时会遇到这些问题(即使像Svelte那样是two-way data-binding actually can be made safe)。

* 无状态MVC * 也不适合客户端

MVC在 * 服务器端 * 的流行实现与 * stateless * 同义,因为web服务器通常是无状态的,但是正如Ryan Carniato from SolidJS指出的,在 * 客户端 * MVC框架的发展中:
基本上,无状态MVC架构对于客户端来说是错误的。
因为富客户端(SPA)通常需要是有状态的,即,富客户端需要保存用户状态,并且快速地处理用户交互,而不必要求到服务器的往返。
但在某种意义上,React * 就是 * MVC
也就是说,您可以说React实际上在某种意义上是MVC(更接近MVC的原始含义)。
React是垂直地(通过关注点)分割MVC,而不是水平地(通过技术),这是人们对MVC模式所做的。看,MVC已经变成了一个layered architecture,视图作为一个薄层在上面。(尽管最初的意思不是这样[1])。
因此,您可以说React中的组件最初是小型垂直切片封装的MVC:包含state/useState(模型)、rendering(视图)和控制流逻辑(本地化的迷你控制器,如果你愿意的话)。
目前,组件(在前端库如React和SolidJS中)混合了渲染和渲染逻辑。组件的范围从完全面向视图到完全面向控件。
但大多数组件都介于两者之间;具有呈现输出和控制流逻辑两者的位。

组件通常是视图控制器

所以目前,React组件已经变成了一个垂直切片的ViewController,其中Model位包含在其他地方。例如,在状态处理库中,如集中的Redux,或在单独/正交的Recoil存储中。或者只是伪包含在组件中,带有钩子,如useState(而实际上包含在React本身中)。
因此,组件目前可视为视图控制器
看到React组件与iOS的UIViewControllers的相似性是很有趣的[2]。也许这种来自原生iOS开发的思维模式影响了组件的创建,考虑到Facebook与React + React原生组合旨在拥有相同的框架和思维模式来处理纯原生和Web。
'视图控制器(VC)管理视图并帮助创建应用程序的UI。它与模型对象和其他控制器对象协调。众所周知,它同时扮演视图对象和控制器对象的角色。每个VC显示自己的应用程序内容视图。'-iOS ViewController lifecycle
如果你需要进一步的说服力,只要阅读Apple's documentation of ViewControllers in Swift,想象他们在谈论一个React组件。实际上没有阻力(又名认知失调)。

组件作为视图,挂钩作为控制器

如今,随着大量组件逻辑被提取到Hooks中,ryanflorenceswizecteller注意到您可以看到:

    • 组件更多的是视图,而挂钩是控制器**。

在React的Remix SSR框架中,victorsavkin指出:

  • "加载器+操作组合类似于MVC中的控制器。React组件基本上是视图。"*
    • 注:**

[1]-有趣的是,前端编程(React)仍然在努力实现MVC,因为它最初是由Trygve Reenskaug在1979年提出的,他已经用Smalltalk实现了它。它是通过将界面/屏幕分割成无数微小的原子/组件来实现的,每个原子a组件都遵循MVC模式:请参见MVC is not an Architecture中的 “屏幕上的每个小部件都有自己的模型、控制器和视图。" 尽管这种方法有一些缺点,特别是与同步状态变化有关的缺点,正如this excellent and visual MVC explainer article中以 “有时MVC应用于单个部件级别..." 开头的部分所指出的那样。(请参见MVC-widget could look like with React+XState中的内容)

然而,在React中,同步状态是通过“prop drilling”(这成为了它自己的问题,由Redux等集中状态库解决)结合Flux架构的单向数据流(由Facebook引入,经常用于React,如Redux)来处理的。

[2]-需要注意的是,iOS ViewController -就像后端MVC模式中的Controller一样-可能有更广泛的问题(像跨组件通信,更少的封装),因为React组件是React的JSX/DOM层次结构和Flux体系结构的一部分。关于“控制器”的实际含义可能有几种不同的定义,但出于我的意图和目的,我将它视为控制流逻辑的中心(它可以用于简单的视图渲染,或者在后端的情况下,也可以用于路由和模型编排)。

izkcnapc

izkcnapc3#

我觉得公认的答案有点不完整,所以只想添加三个要点(当通量/redux用于说明答案时)。
从此处开始:https://medium.com/createdd-notes/understanding-mvc-architecture-with-react-6cd38e91fefd

  • 处理流程是单向的,而不是双向的
  • 存储能够存储任何与应用程序相关的状态,而MVC中的模型被设计为存储单个对象
  • 启动点Dispatcher使调试更加容易

相关问题