开头先做个声名,本文只是用通俗易懂的方法说了Vue响应式的原理,并没有非常详细的根据源码进行解析,想要很详细了解的大佬可以略过。
在了解vue双向绑定原理之前我们先来看一下Object.defineProperty()这个方法。
Object.definePropetry()方法会直接在一个对象上定义一个新属性,或者修改一个对象现有属性并返回这个对象。
现在来看vue响应式数据的实现方法,就是基于Object.defineProperty方法对每一个对象中的每一个属性设置get和set方法。
get和set方法的作用:
get和set都是一个函数,其中get是每当属性被访问时就会触发,set是当属性被赋值时就会触发。
贴段简化代码
var obj={
name:"小明"
}
Object.defineProperty(obj,"name",{
get() {
console.log("get触发")
},
set(val){
console.log("set触发",val)
}
})
然后Vue在set和get属性处添加了方法,只要触发,就执行各自对应的方法。
然后呢,再说回到data,data中声明的每个属性下都有一个数组,保存着谁使用了这个属性。这时如果有哪个页面使用了data中的这个属性,那么这个页面就会被保存到这个数组中,然后当它发生改变时,就能通知依赖的页面进行改变,从而完成页面的更新。
保存的过程就是依赖收集,把 依赖了我(使用了我的东西),统统保存起来。
可是,保存在哪里,具体保存的是什么东西,我们这里暂时不深入。
这里是一个简单的Vue数据打印,只保留了想看的部分。可以看到,name 属性,使用了 一个 dep 保存了 页面A 这个依赖,而保存的实际上是 页面A的 Watcher。(简单说一下,watcher 是什么,每个 Vue 实例都会拥有一个专属的 watcher,可用于实例更新)。
最后稍微来个总结
- Object.defineProperty - get ,用于 依赖收集
- Object.defineProperty - set,用于 依赖更新
- 每个 data 声明的属性,都拥有一个的专属依赖收集器 subs
- 依赖收集器 subs 保存的依赖是 watcher
- watcher 可用于 进行视图更新
最后说一下,本文是看了神仙朱大佬的帖子做的学习总结,有不够好的地方大家可以指出,欢迎。