敲黑板划重点,这是考点。vue带给我们便利,我们也要知其然知其所以然,才能称对得起码农菜鸟这个称谓,才能和面试官闲话把vue家常。接下来,请集中注意力,我们来抽丝剥茧。
一、原理
先来看js对象的基本方法defineProperty():
var obj = {};
Object.defineProperty(obj, 'name', {
get: function() {
console.log('我获取了name属性')
return val;
},
set: function (newVal) {
console.log('我设置了name属性为:' + newVal)
}
})
obj.name = '魔丸';//在设置obj的name属性时,触发了set方法
var val = obj.name;//在获取obj的name属性时,触发了get方法
相信这个方法大家都了解,没错,vue就是运用了该方法实现的双向数据绑定。唠叨:vue.js 采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()
来劫持各个属性的setter
,getter
,在数据变动时发布消息给订阅者,触发相应的监听回调。也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随之发生改变,大家都是拴在一条绳子上的蚂蚱。是不是似懂非懂,别急,继续上网图:
原理图讲解:
1 .observer(数据监听器/观察者):用来实现对vue的data中定义的每个属性循环用Object.defineProperty()实现数据劫持,以便利用其中的setter和getter,然后通知watcher(订阅者),watcher会触发它的update方法,对视图进行更新。
**2.指令解析器Compile: **对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,并绑定相应的更新函数。
3 .订阅者:
- 连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图。
- 在vue中v-model,v-name,{{}}等都可以对数据进行显示,假如一个属性同时绑定了这三个指令,那么当这个属性值改变时,这三个指令对应的html视图都要改变。每当用到这样一个指令,就在Dep中增加一个订阅者。订阅者只是更新自己的指令对应的数据,也就是 v-model='name' 和 {{name}} 有两个对应的订阅者,各自管理自己的地方。
4.消息订阅器Dep: 收集订阅者,数据变动后会触发notify,调用订阅者的update方法。
5.mvvm入口函数: 整合以上三者。
二、just do it
1.Observer实现思路:observe对被监听数据对象进行递归遍历,包括子属性对象的属性,都加上 setter 和 getter。这样的话,给这个对象的某个值赋值,就会触发setter,进而监听到数据变化。
双向绑定
{{name}}