三代目: M-V-C:(模型,视图,控制器)
现在网上有很多关于mvc的介绍,让人纠结的是他们各不相同,而且有的根本就说的不对, 对于框架模式这东西,没有一个严格的规定说这样搞是 mvc 那样就不是。 甚至连mvc本身也有很多变种,我们只要从根源上理解这个东西就行。
我就不扒祖坟了,咱们只需要知道它已经存在了 30多年就行了。
我们思考一下 UI(图形化用户界面) 的本质:
为什么要有UI, 在计算机眼中 一切即数据,其实要是深挖这个问题,数据与操作其实都是 0 1 组成的机器码,只不过 CPU运行的时候用指定寄存器的数据当做指令罢了,也就是说决定一个数据到底是数据还是指令 只取决于他所在的寄存器位置。(好了好了 扯远了,往回跑。。) 数据的操作是抽象的,是专业人士干的事情, 计算机为了走进千家万户, 必须提供一种傻瓜式的操作方式,于是UI诞生了。。。 用一句话解释UI就是:
他是数据到图像的一种映射程序;
刚才说了它是一种映射程序,用户通过操作图像上的按钮,来达到操作数据的目的,数据被用户改变后,肯定需要从新生成映射。
请允许我向上一张老掉牙的图:
说说这里面 Modle View Controller 是干什么的:
1.
View: 放置视图相关的代码,原则上里面不应该有任何业务逻辑。
2.
Controller: 放置视图与模型之间的映射,原则上这里应该很薄,他只放一些事件绑定相关的代码(router),但并不实现真正的功能,他只是一个桥梁。
3.
Modle: 这里的modle不是说 实体类, 他是主要实现逻辑的地方。
那还是上面 买水果的例子,那么在MVC下该如何设计呢:
概念 |
解释 |
view层 |
放置界面代码,以及一些刷新逻辑 如数据中的 0 1 转成 男 女 |
controller层 |
放置一些绑定逻辑。完成router,不实现函数体。 |
model层 |
接收view的注册,当自身数据变化时,执行view的刷新函数。 业务逻辑都在这里 |
他是这样一个流程:
1.创建显示苹果数量的控件。
2.将上面控件注册到model中。(设置关联的数据,–苹果数变量)
3.修改model中 苹果数变量 。
4.由于苹果数变量被修改,触发所有绑定在上面的控件(view)从新执行刷新函数。
5.显示苹果数量的控件被更新。
这样便解决了大部分界面与逻辑耦合的问题,但是它并不完美:
View 和 Model 并不是完全脱离的,还是有一些逻辑耦合,因为需要根据修改后的model从新刷新view。 难免view里面沾染一点model的结构。
代码量膨胀。
不方便进行更精细的颗粒化控制。(因为view只知道 model被改了,但不知道谁改的!)
- model在对应多个view的时候,很难都伺候到位。
于是。。。
四代目: M-V-P:(模型,视图,派发器)
请允许我再上一张老图:
针对mvc的一些问题,在mvp模式下, 斩断了 view 与 model的关系, 当m 改变时,m 通知 p 去改变v, 所以v变得更纯洁(刷新逻辑被移动到了p层), 为了保证m可以最大程度的复用 一部分业务逻辑也从 m 转移到了p所以 mvp下 p 非常厚实。
mvp中最后改变v的是p那么在 v与p 之间会有一个接口,解决怎么转换以及传值的问题。
五代目: M-V-VM:(模型,视图,抽象视图)
MVVM,最早来自于微软社区,用于WPF
Model-View-ViewModel的关系图:
mvvm 与 mvp 的最大区别就是它使用
数据绑定(Data Binding)、依赖属性(Dependency Property)、命令(Command)、路由事件(Routed Event) 来搞定与view层的交互, 但是这种绑定是与某种具体技术栈相关的, ViewModel从Model中抽象而来,但更贴近于业务模型, 比如你Model中某字段是 true false, ViewModel中可能就是 “黑”,”白”等 这种更贴近业务场景的描述。 ViewModel中的属性直接与某具体控件的属性相绑定。 也就是说当某具体控件发生变化,ViewModel中的 某个字段就会跟着变化,然后Model中的字段也会进一步变化。
以上述为例:
用户使用UI修改了性别字段:
1.操作触发绑定在UI上的事件(Data Binding 自动完成)
2.事件进入vm层,根据绑定规则,找出对应的vm字段, (如表示性别的组件绑定的是vm中的sex字段)
3.vm上的sex被设置成true,(view层上值为”男” “女”,但是在抽象的vm层中我们用 bool 来表示这个字段)
4.同理寻找m层上的对应字段,m上的sex被vm修改成1
5.m找到所有与sex字段有绑定关系的vm通知他们更新。
6.所有接到通知的vm更新sex字段。
7.vm寻找所有与sex字段有绑定关系的view层控件,通知他们更新(Data Binding 自动完成)。
8.view被更新。所有涉及到sex字段的组件都被刷新。
有时候这个流程未必是从 1 步开始,如果直接对 m 进行修改,则就是从第 4 步开始的。
同理如果没有view层,则没有必要进行 7 , 8步骤。
这就是说 mvvm 下可以完全干掉 view 层, 方便的进行自动化测试。
小结 (推送/订阅 这个是数据驱动的核心)
不管是 mvc 还是 mvp 或 mvvm ,他们都是
数据驱动 的。核心上基于
m 推送消息,v或p来订阅 这个模型。使用者需要维护的不再是 UI 树,而是抽象的数据。(通过数据,可以随时构建出新的 UI 树), 当 UI 的状态一旦多起来,这种框架模式的优势便体现出来了。 因为维护数据可比维护 UI 状态爽多了。
前端中的mvc:
并不是说 m v c 三者一定要独立出现才行,比如 Backbone。js 它的 controller 层只是一个 router。 其实在传统 mvc 中 controller 里本来就没有太多的逻辑,他只是一个事件的”传递者”, 加之 javascript 中人们习惯使用匿名函数当事件回调,这样就等于直接在 view 层中把功能函数实现了。 所以 view 与 controller 合并 或者 controller 与model 合并都有可能。
JavaScript
1
2
3 |
$(xxx).click(function(e){
console.log(e);
}) |
本文版权归传智播客web前端开发学院所有,欢迎转载,转载请注明作者出处,谢谢!
作者:传智播客web前端培训学院;
首发:http://www.itcast.cn/web/