故心故心故心故心小故冲啊
文章目录
function initData (vm: Component) {
...
// observe data
observe(data, true /* asRootData */)
}
最重要的就是这一步,把数据添加到观察者中 也就是把数据添加到observe()这个方法
observe()这个方法干了什么?
将data数据变成可观察的Observe实例对象
Observe实例对象又干了啥?
Observer`会对对象的每个属性进行劫持
怎么实现劫持?
walk(obj: Object) {
const keys = Object.keys(obj)
for (let i = 0; i < keys.length; i++) {
defineReactive(obj, keys[i])
}
}
*/
export function defineReactive(
...
Object.defineProperty(obj, key, {
get: function reactiveGetter() {
if (Dep.target) {
dep.depend()
if (childOb) {
childOb.dep.depend()
if (Array.isArray(value)) {
dependArray(value)
}
}
}
}
set: function reactiveSetter(newVal) {
dep.notify() ---去通知所有watcher去更新
}
})
)
在Observer这个实例对象中循环遍历添加defineReactive方法,而defineReactive通过Object.defineProperty进行对数据的劫持
那么又是如何通知视图变化呢?
get方法收集依赖
set方法触发依赖
Vue首先会调用所有使用的数据,从而触发所有的 getter 函数,进而通过Dep对象收集所有响应式依赖,调用所有Watcher执行Render 操作,其中会进行虚拟Dom的存储和比较,进而渲染页面。
当有数据变更时会触发 setter 函数,触发dep.notify(),进而调用Watcher的update,推入Vue的异步观察队列中,最终调用Watch的getter或者cb方法进而调用vm._update(),再调用vm__patch__方法进行虚拟DOM的diff,并最终渲染到页面。
双向数据绑定原理
vue采用数据劫持和发布订阅模式来实现的双向数据绑定,主要通过Object.definePropetry来劫持各个属性,在数据变动时发布消息给订阅者,触发相应的监听回调。
总结的来说就是首先在初始化数据initData()这个方法中通过observe()方法把数据变为可观察对象
在Observe()这个类中通过循环遍历地每一个属性添加defineReactive这个方法,而defineReactive()就是采用数据劫持Object.definePropetry()进行对每一个数据的劫持,当数据改变的时候,会调用dep中的notify方法去通知watcher去更新