为何点击下面的button
界面会出现自增?segmentfault
<div id="example-2"> <simple-counter></simple-counter> </div> Vue.component('simple-counter', { template: '<button v-on:click="counter += 1">{{ counter }} </button>', data: function () { return { counter: 0 } } }) new Vue({ el: '#example-2'})
数据定义
;数据绑定
;数据响应
;{counter:0}
;observe(data, this)
;observe()
过程当中会将data
这个对象劫持,经过Object.defineProperty
将data
上全部的属性绑定上getter
和setter
函数;(这是针对对象,对于数组,Vue
经过改写数组的原生方法来劫持);counter
的值就会触发getter()
;要是谁改变了counter
的值就会触发setter()
;好比上述代码中的button
绑定{{count}}
的时候必定会触发getter()
;若是是count
的值发生改变就必定会触发setter()
button
中绑定{{count}}
;button
会产生一个Watcher(vm, exp, cb(newValue,oldValue))
,vm
是Vue
对象,exp
是数据绑定的数据;cb()
的逻辑是用来更新页面。如今的问题是如何将数据的变化和Watcher
关联起来。在这里用到了一个重要的思想就是发布订阅模式
;Watcher
初始化的时候会将Dep.target
设置为this
,也就是Watcher
本身,同时会触发count
的getter
方法,getter
里面会调用Dep
的depend
方法,depend
方法会调用Watcher
的addDep
方法,addDep
方法就是将Watcher
本身存放在Dep
的事件池里面。数组
class Dep { constructor() { this.id = uid++; this.subs = []; } addSub(sub) { this.subs.push(sub) } depend() { if (Dep.target) { Dep.target.addDep(this) } } removeSub(sub) { let ind = this.subs.findIndex(sub); this.subs.splice(ind, 1) } notify() { this.subs.forEach(sub => sub.update()) } } Dep.target = null;
count
的值改变,会触发setter
里面的方法,这个方法会调用dep.notify()
;它会告知Dep的事件池里的存放的Watcher
去执行它的update()
方法;Watcher
的update()
方法;这个方法里面会获取count
的新的值,给它的回调cb()
,去更新视图。Vue
官方给出的示意图的含义。