资讯专栏INFORMATION COLUMN

浅谈MVC,MVP,MVVM渐进变化及React与Vue比较

DrizzleX / 3306人阅读

摘要:将注意力集中保持在核心库,而将其他功能如路由和全局状态管理交给相关的库。此示例使用类似的语法,称为。执行更快,因为它在编译为代码后进行了优化。基于的模板使得将已有的应用逐步迁移到更为容易。

前言

因为没有明确的界定,这里不讨论正确与否,只表达个人对前端MV*架构模式理解看法,再比较React和Vue两种框架不同.
写完之后我知道这文章好水,特别是框架对比部分都是别人说烂的,而我也是打算把这作为长期文章来写,慢慢梳理深入,每次有新的理解就更新文章,我挺期待之后到了超过字数限制不得不写成系列文章的那一天.

2018/04/28 新增声明式渲染 && 生命周期对比 && 状态(State) OR 属性(Data) && Props组件通信
2018/05/02 新增状态管理
2018/06/07 新增mobx状态管理
2018/11/06 补充更新机制和状态管理对比

MVC

MVC全名是Model View Controller,把应用程序分成三部分分别是:

Model(业务模型): 用于管理应用程序数据处理逻辑的部分,通过观察者模式(Pub&Sub / Events)发送消息给View;

View(视图界面): 用于处理数据显示的部分,注册并接收Model的数据更新视图,通常视图是依据模型数据创建的;

Controller(控制器): 用于连接模型和视图控制应用程序的流程(事件绑定等),通常控制器负责响应View的事件(路由,键盘,鼠标等),调用Model的接口进行操作;


(这些简单的东西我就懒得特意画图了,直接百度图片找张清晰的拿来用的..)
(更多内容请自行查阅,本节到此为止了.)

流程

当用户在视图界面中发生交互事件,View捕获到这个操作会把处理的权利交移给Controller;

Controller会对来自View数据进行预处理并决定调用Model的相关暴露接口;

Model执行相关的业务逻辑更改数据之后会通知有关的View重新渲染;

View收到通知后从Model请求最新的数据,然后重新渲染相关视图界面;

还有一种情况: MVC允许在不改变视图外观的情况下改变视图对用户输入的响应方式,只要用不同种类的controller实例替换即可。例如改变URL触发hashChange事件,用户不经过View直接到达Controller最后再影响回View.

优点:

耦合性低,MVC 分层有助于管理复杂的应用程序,同时也让应用程序的测试更加容易;

重用性高,多个视图能共享一个模型,可以做到多视图同时更新;

生命周期成本低,MVC使开发和维护用户接口的技术含量降低;

部署快,只需要部署对应部分代码而不是完整项目;

可维护性高,分离视图层和业务逻辑层也使得应用更易于维护和修改;

有利软件工程化管理,可以使用控制器来联接不同的模型和视图去完成用户的需求;

缺点:

没有明确的定义,完全理解MVC并不是很容易,现存就有很多对MVC不同解读实现的方式;

不适合小型,中等规模的应用程序,花费大量时间将MVC应用到规模并不是很大的应用程序通常会得不偿失;

增加系统结构和实现的复杂性,对于简单的界面,会增加结构的复杂性,并可能产生过多的更新操作,降低运行效率;

视图与控制器间的过于紧密的连接,视图没有控制器的存在,其应用是很有限的,反之亦然,导致测试困难(依据模型数据创建部分);

视图对模型数据的低效率访问,依据模型操作接口的不同,视图可能需要多次调用才能获得足够的显示数据;

观察者模式由于事件触发的隐式行为可能导致很难查找问题的来源并影响其解决;

MVP

MVP全名是Model-View-Presenter,从经典的模式MVC演变而来,分两种情况:

Passive View(被动视图)

Presenter占据绝对主导地位,掌控著Model和View,而后两者之间互不联系.

Model(业务模型): 用于管理应用程序数据处理逻辑的部分,通过观察者模式(Pub&Sub / Events)发送消息给Presenter;

View(视图界面): 用于处理数据显示的部分,传递事件和提供相关接口给Presenter;

Presenter(派发器): 作为中间层同步控制著Model数据修改和View视图变化;


(这些简单的东西我就懒得特意画图了,直接百度图片找张清晰的拿来用的..)
(更多内容请自行查阅,本节到此为止了.)

流程:

当用户在视图界面中发生交互事件,View捕获到这个操作会把处理的权利交移给Presenter进行处理;

Presenter需要时候可以获取Model其中的数据,并对Model进行操作更新;

Model数据变化之后会通知Presenter;

Presenter收到通知后会执行View提供的相关接口重新渲染相关视图界面;

MVC和MVP(Passive View)区别:

后者View和Model完全解耦,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部;

前者Controller只能通过Model间接触发View自行更新视图,后者View不再负责更新视图,而是提供接口给Presenter执行;

Supervising Controller(监督控制器)

Presenter依旧占据主导地位,但是会把一部分简单的视图逻辑(如双向绑定)交还给View和Model进行处理,自身负责其他复杂的视图逻辑.

Model(业务模型): 用于管理应用程序数据处理逻辑的部分,通过观察者模式(Pub&Sub / Events)发送消息给Presenter或者View;

View(视图界面): 用于处理数据显示的部分和接管部分简单的视图逻辑,同步简单的视图和模型的状态,传递事件和提供相关接口给Presenter;

Presenter(派发器): 作为中间层同步控制著Model数据修改和View视图变化;

MVC和MVP(Supervising Controller)区别:
1, 视图支持Presenter和View两种途径更新;

优点:

1, 模型与视图高度分离,我们可以修改视图而不影响模型;
2, 可以更高效地使用模型,因为所有的交互都发生在一个地方——Presenter内部;
3, 可以将一个Presenter用于多个视图,而不需要改变Presenter的逻辑;
4, 如果把逻辑放在Presenter中,就可以脱离用户接口来测试这些逻辑(单元测试);

缺点:

1, 由于对视图的渲染放在了Presenter中,所以View和Presenter的交互会过于频繁并且难以维护;

MVVM

MVVM全名是Model-View-ViewModel,本质上就是MVC的改进版,也可以说是MVP的改良版,把应用程序分成三部分分别是:

Model(业务模型): 用于管理应用程序数据;

View(视图界面): 通过使用模板语法来声明式的将数据渲染进DOM;

ViewModel(视图模型): 包含了领域模型(Domain Model)和视图的状态(State),核心就是双向绑定技术(Two-Way-Data-Binding),View和Model之间数据同步操作交由给内部的Binder/Data-binding engine处理;

MVP和MVVM区别: 它使用 数据绑定(Data Binding)依赖属性(Dependency Property)命令(Command)路由事件(Routed Event) 来搞定与view层的交互, 当ViewModel对Model进行更新的时候,会通过数据绑定更新到View.

(这些简单的东西我就懒得特意画图了,直接百度图片找张清晰的拿来用的..)
(更多内容请自行查阅,本节到此为止了.)

优点:

双向绑定(data-binding):View的变动,自动反映在 ViewModel,反之亦然;

解放MVP大量手动同步状态的问题,提高了代码的可维护性;

简化测试,Model正确就能保证View输出;

缺点:

大型项目的绑定数据较多会提高维护成本;

View里的数据绑定无法检测断点,只能从Model下手;

React VS Vue

两个框架是现在最热门的选择之一,它们既类似又不同.

使用 Virtual DOM

提供了响应式 (Reactive) 和组件化 (Composable) 的视图组件。

将注意力集中保持在核心库,而将其他功能如路由和全局状态管理交给相关的库。

React就是MVC里的V,只专注视图层,而Vue算是MVVM框架,双向绑定是特色之一.

介绍

我们先看看它们自己的官方介绍:

React

React is a JavaScript library for building user interfaces.

Declarative: React makes it painless to create interactive UIs. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes. Declarative views make your code more predictable, simpler to understand, and easier to debug.

Component-Based: Build encapsulated components that manage their own state, then compose them to make complex UIs. Since component logic is written in JavaScript instead of templates, you can easily pass rich data through your app and keep state out of the DOM.

Learn Once, Write Anywhere: We don"t make assumptions about the rest of your technology stack, so you can develop new features in React without rewriting existing code. React can also render on the server using Node and power mobile apps using React Native.

翻译:

React是一个用于构建用户界面的Javascript库.

声明式: React让你无痛创建交互式UI界面,为你的App应用程序里的每个状态设计简单的视图,并且当你的数据改变之后会进行高效地更新和正确地渲染对应组件,声明式视图让你的代码更可预测、更易于理解和更容易调试.

组件化: 构建封装组件管理它们自己的内部状态,然后组合它们去构建复杂UI界面.因为组件逻辑写在Javascript而不是模板里,你能轻松注入丰富的数据到你的App并且状态脱离在Dom之外.

只需学习一次,就能用到任何地方,我们不对你的其余技术栈作出假设,所以你能在React里开发新的特性而不需要重写你的现有代码.React也能使用Nodejs进行服务器渲染和使用React Native进行移动端的丰富开发.

Vue

Vue (pronounced /vjuː/, like view) is a progressive framework for building user interfaces. Unlike other monolithic frameworks, Vue is designed from the ground up to be incrementally adoptable. The core library is focused on the view layer only, and is easy to pick up and integrate with other libraries or existing projects. On the other hand, Vue is also perfectly capable of powering sophisticated Single-Page Applications when used in combination with modern tooling and supporting libraries.

翻译:

Vue.js (读音 /vjuː/,类似于 view) 是一套构建用户界面的渐进式框架。与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计。Vue 的核心库只关注视图层,它不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与单文件组件和 Vue 生态系统支持的库结合使用时,Vue 也完全能够为复杂的单页应用程序提供驱动。

声明式渲染 React(官方写法)

React 组件实现一个 render() 方法,它接收输入数据并返回显示的内容。此示例使用类似XML的语法,称为 JSX 。输入数据可以通过 this.props 传入组件,被 render() 访问。

class HelloMessage extends React.Component {
  render() {
    return (
      
Hello {this.props.name}
); } } ReactDOM.render( , mountNode );
Vue(官方写法)

Vue.js 的核心是一个允许采用简洁的模板语法来声明式的将数据渲染进 DOM 的系统

{{ message }}
// --------省略-------- var app = new Vue({ el: "#app", data: { message: "Hello Vue!" } })
HTML React JSX

他是 JavaScrip 的一种扩展语法。 React 官方推荐使用这种语法来描述 UI 信息。JSX 可能会让你想起某种模板语言,但是它具有 JavaScrip 的全部能力,从本质上讲,JSX 只是为 React.createElement(component, props, ...children) 函数提供的语法糖。

JSX 执行更快,因为它在编译为 JavaScript 代码后进行了优化。

它是类型安全的,在编译过程中就能发现错误。

使用 JSX 编写模板更加简单快速。

JSX 对使用React 不是必须的。

Vue Templates

Vue.js 使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。所有 Vue.js 的模板都是合法的 HTML ,所以能被遵循规范的浏览器和 HTML 解析器解析。
在底层的实现上,Vue 将模板编译成虚拟 DOM 渲染函数。结合响应系统,在应用状态改变时,Vue 能够智能地计算出重新渲染组件的最小代价并应用到 DOM 操作上。
事实上 Vue 也提供了渲染函数,甚至支持 JSX。然而,默认推荐的还是模板。

对于很多习惯了 HTML 的开发者来说,模板比起 JSX 读写起来更自然。这里当然有主观偏好的成分,但如果这种区别会导致开发效率的提升,那么它就有客观的价值存在。

基于 HTML 的模板使得将已有的应用逐步迁移到 Vue 更为容易。

这也使得设计师和新人开发者更容易理解和参与到项目中。

你甚至可以使用其他模板预处理器,比如 Pug 来书写 Vue 的模板。

对比

个人感觉两者其实上手速度都挺快,相比之下JSX除了修改部分属性名字跟普通HTML变化不算大,Templates额外添加很多自定义功能帮助开发者做更多的事,框架痕迹也比较重.
我们可以把组件区分为两类:一类是偏视图表现的 (presentational)推荐使用模板,一类则是偏逻辑的 (logical)推荐使用 JSX 或渲染函数。

//Jsx写法
    { todos.map(item =>
  1. {todo.text}
  2. ) }
//Templates写法
  1. {{ todo.text }}
CSS React

React 中推荐通过 CSS-in-JS 的方案实现的 (比如 styled-components、glamorous 和 emotion),虽然在构建时将 CSS 提取到一个多带带的样式表是支持的,但 bundle 里通常还是需要一个运行时程序来让这些样式生效。当你能够利用 JavaScript 灵活处理样式的同时,也需要权衡 bundle 的尺寸和运行时的开销

var styleObj = { color:"blue", fontSize:40, fontWeight:"normal" };
--------省略--------

Hello

Vue

Vue 设置样式的默认方法是单文件组件里类似 style 的标签。让你可以在同一个文件里完全控制 CSS,将其作为组件代码的一部分。

这个可选 scoped 属性会自动添加一个唯一的属性 (比如 data-v-21e5b78) 为组件内 CSS 指定作用域,编译的时候 .list-container:hover 会被编译成类似 .list-container[data-v-21e5b78]:hover。
最后,Vue 的单文件组件里的样式设置是非常灵活的。通过 vue-loader,你可以使用任意预处理器、后处理器,甚至深度集成 CSS Modules——全部都在