本文来自我的博客这个想法不一定对系列,so,这个想法不一定对 *

一切皆为数据(0,1),一切皆可量化

不管承不承认,页面的展示都是数据的可视化。HTML 是数据,CSS 是数据,JS 也是数据。只是这些数据的组合最终变成了我们想要的效果。

最为直观的是,我们在开发者工具 Console 控制台中,输入任何形式的数据并点击 Enter 时,最终会在下方显示出来(前提是输入正确的数据类型和格式)。又或者,我们用某些参数从服务请求一个 JSON 文件,浏览器上就会展示文件内容。数据 => 视图,就是这么简单直接。

引子

然而,实际上的情况远远比这复杂。为了更好的视觉享受和用户体验,浏览器上的页面效果越来越炫,交互逻辑也越来越复杂。我们拿到的第一手数据(或来自用户,或来自服务)已经不能直接用来展示了,而是要经过相应的逻辑处理(在这里我们称第一手数据为源数据,经过逻辑处理后的数据称为目标数据)。视图上的数据就是目标数据的映射。

而处理后的数据又该如何展示呢?是基于 DOM 做操作,还是基于目标数据重新渲染呢?两者都可,前者是以 jQuery 为代表,后者则是以 Vue 等新框架为主。举个例子 *,对于某个 DOM 元素的显隐。

< !--jQuery -->
  <div id='jquery'></div>
$('#jquery').hide();

< !–Vue >
<div id=‘jquery’ v-show={id[jquery]}></div>
data: {
id: {
jquery: fasle
}
}

复制代码

基于 DOM 操作, 如果我们需要对这个 DOM 随时改变显隐,就需要不断操作 DOM 来更改样式。 如果基于数据操作,我们只需要更改 jQuery 的值即可。

我们再回到刚才的话题,对于复杂的交互页面,数据 => 视图 的关系已经不再像之前那么纯净了。为了应付复杂的场景,数据视图 不再是狭义上的数据和视图。数据包括了数据和数据相关的操作,视图包括了视图和对视图相关的一些操作。

MV* 模式

借用MV* 框架模式,这里的 数据视图 对应着 ModelView. 简单点的页面,Model - View 完全能够应付过来。但是复杂的场景,ModelView 会分担太多的逻辑而显得臃肿,甚至可能包含了不在自己职责范围内的逻辑。

此时我们就要借助第三者来协调 ModelView 之间的关系。如何合作,其实也早有了相应的解决方案。比如 MVC、MVP、MVVM。因为重点始终在于协调 ModelView,所以它们统称为 MV*

MVC&MVP.jpg

MVC (Model( 模型)-View(视图)-Controller(控制器)), MVP (Model( 模型)-View(视图)-Presenter(中介者)) 以及 MVVM (Model( 模型)-View(视图)-ViewModel(视图模型)),是种模式也是种抽象的概念。

每一种模式在实践中可能存在着不同的变体,但这不妨碍它们属于同一个模式。每一种模式的不同变体都是为了解决不同问题而产生的,所以它们没有什么优劣之分。

现在我们就把三种模式拟人化来阐述不同模式的运作方式。

由四节电池驱动的 J-20 模型:

J-20.jpg

MVC

公司:飞机模型制造商 => 生产的飞机模型可以自主塑形。

模式:MVC

飞机模型 V:由模型数据生产出的模型。职责有:由模型数据自主塑形、将收集用户反馈并转发。

工程师 M:负责将客服的需求参数转换成最终的模型数据。职责有:对数据的操作、通知飞机模型更新。

工程师 C:协调 M 和 V。负责响应用户、调用工程师 M 生成目标数据。

首先我们要知道,客户提出了想要一个 60cm * 60cm 的飞机模型,这个需求到了制造商那里肯定不是给出个 60cm * 60cm 的小方块,而是根据需求计算处理生产真正的飞机模型(比如什么样的造型设计才能最大减少阻力),工程师 M 的工作之一就是根据原始数据并结合特定的逻辑规则给出最终的模型数据。

现在,用户手里有一飞机模型 V,不过这个飞机模型的飞机双翼和用户想象的不一样。于是用户根据飞机模型上提供的方式反馈了问题(比如飞机模型提供了留言功能,用来收集用户反馈)。工程师 C 收到了反馈后,把工程师 M 拉过来对数据进行处理并生成新的模型数据,并让工程师 M 通知到共享相同数据的飞机模型去更新数据自主调整。

插一句,说到调整,我们有两种方式。一个是,我们可以针对用户不满意的地方(飞机双翼)进行调整。一个是,我们飞机模型格式化按照最新的数据模型重新初始化一下。前者可以认为就是基于 DOM 操作的方式,后者就是基于数据的处理方式。

在 MVC 中,Model 和 View 之间耦合,视图的更新需要 Model 去直接通知。Model 内因为有 View 的引用才能让视图更新。

MVC.png

MVP

如果 Model 只想做数据相关的操作,把通知 View 的逻辑挪到了 Control 里,这时 Control 摇身一变称为了 Presenter。因为解耦了 Model 和 View,也使得它们的职责划分更加清晰。

公司:飞机模型制造商 => 生产的飞机模型可以自主塑形。

模式:MVP

飞机模型 V:由模型数据生产出的模型。职责有:由模型数据自主塑形、将收集用户反馈并转发。

工程师 M:负责将客服的需求参数转换成最终的模型数据。职责有:对数据的操作。

工程师 P:协调 M 和 V。负责响应用户、调用工程师 M 生成目标数据、更新视图。

在 MVP 模式中,工程师 M 的工作专注于数据,通知的活甩给了工程师 P。 和 MVC 同样的场景,工程师 P 接到反馈后,把工程师 M 拉过来处理了数据,然后又让飞机模型依据已经处理后的数据自主调整。每次数据的变化都要主动去通知视图更新。

MVP.png

MVVM

如果数据变化能够自主触发视图更新,对 Presenter 来说也会轻松不少。于是 Presenter 再次摇身一变 称为了 ViewModel。

公司:飞机模型制造商 => 生产的飞机模型可以自主塑形。

模式:MVVM

飞机模型 V:由模型数据生产出的模型。职责有:由模型数据自主塑形、将收集用户反馈并转发。

工程师 M:负责将客服的需求参数转换成最终的模型数据。职责有:对数据的操作。

工程师 VM:协调 M 和 V。负责响应用户、调用工程师 M 生成目标数据并更新视图。

MVVM.png

在 MVVM 中,View 和 Model 的变化似乎不大。为了在数据变化后能够自动更新视图,ViewModel 进行了所谓的数据绑定。ViewModel 将 目标数据 和视图进行了绑定,在最终生成目标数据时,会触发视图的更新。

在这里我们可以想象有两份数据,一份是源数据,一份是目标数据。绑定视图的是目标数据,这样,我们直接修改目标数据时会触发视图更新。如果是源数据经处理后赋给目标数据,目标数据也会改变,也会触发试图更新。

总之,在 MVVM 中,视图是目标数据的可视化,通过改变视图里的数据也就等于改变了目标数据。

和 MVC、MVP 同样的场景,不过科技发达了,工程师 VM 有个自动化处理程序。用户反馈了问题,工程师 VM 的这个自动处理程序接到反馈自动处理并将结果发给飞机模型让其自主调整。

以下是 Vue 的 MVVM 示意图:

mvvmVue.png MVC、MVP 和 MVVM 大致就是如此,根据三种模式以及不同场景,最终演变出了不同的变体。

但是,不同的变体是针对不同问题的解决方案,指不定后来还会有 MVA、MVB..., 谁知道呢

感谢    赞同    分享    收藏    关注    反对    举报    ...