文章目录
最近面试时老被问到双向数据绑定。明明概念看了好几遍,也总结了好几次,但是还是被问住
参考文章 http://www.cnblogs.com/canfoo/p/6891868.html
(很欣赏这篇博客作者的一句话,“再长的路,一步步也能走完。再短的路,不迈开双脚也无法到达。”送给自己)
一、mvc 和 mvvm
(1) MVC
mvc 属于单项通信
MVC是Model-View- Controller的简写,即模型-视图-控制器
C即Controller指的是页面业务逻辑(在后端实现)
使用mvc 的目的就是将M和V的代码分离
也就是View跟Model,必须通过Controller来承上启下
(2)mvvm
MVVM是Model-View-ViewModel的简写。即模型-视图-视图模型。
- 【模型】指的是后端传递的数据。
- 【视图】指的是所看到的页面。
- 【视图模型】mvvm模式的核心,它是连接view和model的桥梁。
1. mvvm的方向
数据双向绑定的概念
由上图可以看出
- 将【模型】转化成【视图】,即将后端传递的数据转化成所看到的页面(实现方式:数据绑定)
- 将【视图】转化成【模型】,将所看到的的页面转化为所看到的数据(实现方式:DOM事件监听)
这两个方法都实现的,我们称为数据双向绑定
2. 总结mvvm
在MVVM的框架下视图和模型是不能直接通信的。它们通过ViewModel来通信。
- ViewModel通常要实现一个observer观察者,当数据发生变化,ViewModel能够监听到数据的这种变化,然后通知到对应的视图做自动更新
- 而当用户操作视图,ViewModel也能监听到视图的变化,然后通知数据做改动,
并且MVVM中的View 和 ViewModel可以互相通信
二、vue
Vue就是基于MVVM模式实现的一套框架
在vue中:
- Model:指的是js中的数据,如对象,数组等等。
- View:指的是页面视图
- viewModel:指的是vue实例化对象
(1) vue数据双向绑定的原理
vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的
vue是通过Object.defineProperty()来实现数据劫持的。
Object.defineProperty( )是用来做什么的?
它可以来控制一个对象属性的一些特有操作,比如读写权、是否可以枚举,这里我们主要先来研究下它对应的两个描述属性get和set
- get
一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。当访问该属性时,该方法会被执行,方法执行时没有参数传入,但是会传入this对象(由于继承关系,这里的this并不一定是定义该属性的对象)。
默认为 undefined。 - set
一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。当属性值修改时,触发执行该方法。该方法将接受唯一参数,即该属性新的参数值。
默认为 undefined。
(2) 实现mvvm主要包含两个方面,数据变化更新视图,视图变化更新数据:
关键点在于data如何更新view,因为view更新data其实可以通过事件监听即可,比如input标签监听 ‘input’ 事件就可以实现了。所以我们着重来分析下,当数据改变,如何更新视图的。
数据更新视图的重点是如何知道数据变了,只要知道数据变了,那么接下去的事都好处理。如何知道数据变了,其实上文我们已经给出答案了,就是通过Object.defineProperty( )对属性设置一个set函数,当数据改变了就会来触发这个函数,所以我们只要将一些需要更新的方法放在这里面就可以实现data更新view了。
实现过程
-
实现一个监听器Observer,用来劫持并监听所有属性,如果有变动的,就通知订阅者。
-
实现一个订阅者Watcher,可以收到属性的变化通知并执行相应的函数,从而更新视图。
-
实现一个解析器Compile,可以扫描和解析每个节点的相关指令,并根据初始化模板数据以及初始化相应的订阅器。
(实现具体代码参考原文)