简单来说用 JavaScript 在浏览器中操作 HTML经历了以下几个阶段:
第一阶段:直接用 javascript 操作 dom 节点,使用浏览器提供的原生API;
第二阶段:由于原生 API 不好用,还要考虑浏览器兼容性,jQuery 横空出世,
以简洁的API迅速俘获了前端开发者的芳心;
第三阶段:MVC 模式,需要服务端的配合,javascript 可以在前端修改服务器渲染后的数据。
现在随着前端页面越来越复杂,用于对于用户的交互性要求也越来越高,仅仅用jQuery是远远不够,
MVVM 模型应运而生。
一、现在我们从 MVC 开始
几乎所有的页面都只干这么一件事:将数据展示给用户看,并处理用户对界面的操作。
MVC 的思想:一句话描述就是Controller负责将Model的数据用View显示出来,换句话说就是在Controller里面把Model的数据赋值给View。
MVC(Model,View,Controller):
Model(模型):是应用程序中用于处理应用程序数据逻辑的部分,通常模型对象负责在数据库中存取数据。
View(视图):是应用程序中处理数据显示的部分,通常视图是依据模型数据创建的。
Controller(控制器):是应用程序中处理用户交互的部分。通常控制器负责从视图读取数据,
控制用户输入,并向模型发送数据。
二、MVVM的诞生
就像我们之前分析MVC是如何合理分配工作的一样,我们需要数据所以有了M,我们需要界面所以有了V,
而我们需要找一个地方把M赋值给V来显示,所以有了C,然而我们忽略了一个很重要的操作:数据解析。
在MVC出生的年代,手机APP的数据往往都比较简单,没有现在那么复杂,所以那时的数据解析很可能一步就解决了,
所以既然有这样一个问题要处理,而面向对象的思想就是用类和对象来解决问题,显然V和M早就被定义死了,
它们都不应该处理“解析数据”的问题,理所应当的,“解析数据”这个问题就交给C来完成了。而现在的手机App功能越来越复杂,
数据结构也越来越复杂,所以数据解析也就没那么简单了。如果我们继续按照MVC的设计思路,将数据解析的部分放到了Controller里面,
那么Controller就将变得相当臃肿。还有相当重要的一点:Controller被设计出来并不是处理数据解析的。
1)、管理自己的生命周期;
2)、处理Controller之间的跳转;
3)、实现Controller容器。
这里面根本没有“数据解析”这一项,所以显然,数据解析也不应该由Controller来完成。那么我们的MVC中,M、V、C都不应该处理数据解析,
那么由谁来呢?这个问题实际上在面向对象的时候相当好回答:既然目前没有类能够处理这个问题,那么就创建一个新的类出来解决不就好了?
所以我们聪明的开发者们就专门为数据解析创建出了一个新的类:ViewModel。这就是MVVM的诞生。
1、MVVM 分为Model、View、ViewModel三者:
- Model:代表数据模型,数据和业务逻辑都在Model层中定义;
- View:代表UI视图,负责数据的展示;
- ViewModel:负责监听Model中数据的改变并且控制视图的更新,处理用户交互操作;
Model和View并无直接关联,而是通过ViewModel来进行联系的,Model和ViewModel之间有着双向数据绑定的联系,
因此当Model中的数据改变时会触发View层的刷新,View中由于用户交互操作而改变的数据也会在Model中同步。
这种模式实现了Model和View的数据自动同步,因此开发者只需要专注对数据的维护操作即可,而不需要自己操作dom。
2、Vue.js 的细节:
Vue.js 可以说是MVVM 架构的最佳实践,专注于 MVVM 中的 ViewModel,不仅做到了数据双向绑定,而且也是一款相对来比较轻量级的JS 库,
API 简洁,很容易上手。Vue的基础知识网上有现成的教程,此处不再赘述, 下面简单了解一下 Vue.js 关于双向绑定的一些实现细节:
Vue.js 是采用 Object.defineProperty 的 getter 和 setter,并结合观察者模式来实现数据绑定的。当把一个普通 Javascript 对象传给 Vue 实例来作
为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty 将它们转为 getter/setter。用户看不到 getter/setter,但是在内部它们让 Vue 追踪依赖,
在属性被访问和修改时通知变化。
Observer :数据监听器,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者,内部采用Object.defineProperty的getter和setter来实现
Compile :指令解析器,它的作用对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数
Watcher :订阅者,作为连接 Observer 和 Compile 的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数
Dep :消息订阅器,内部维护了一个数组,用来收集订阅者(Watcher),数据变动触发notify 函数,再调用订阅者的 update 方法
从图中可以看出,当执行 new Vue() 时,Vue 就进入了初始化阶段,一方面Vue 会遍历 data 选项中的属性,并用 Object.defineProperty 将它们转为 getter/setter,
实现数据变化监听功能;另一方面,Vue 的指令编译器Compile 对元素节点的指令进行扫描和解析,初始化视图,并订阅 Watcher 来更新视图, 此时Wather 会将自己
添加到消息订阅器中(Dep),初始化完毕。
当数据发生变化时,Observer 中的 setter 方法被触发,setter 会立即调用Dep.notify(),Dep 开始遍历所有的订阅者,并调用订阅者的 update 方法,
订阅者收到通知后对视图进行相应的更新。
原文地址:https://www.cnblogs.com/tg666/p/12309821.html