- 找到处理数据响应的代码
initMixin(src/core/instance/index.js)
----------->
initState(src/core/instance/init.js)
----------->
initData(src/core/instance/state.js)
img1
img2
1:取data,如果data选项是函数,则取出该函数返回的值。
2: 判断data是否是纯对象,不是的话重置为空对象,在非生产环境提供提示
3:判断data中的键是否是 methods 和 props中的键,如果是的话,在非生产环境提供提示
4:如果data中的键不是以“$”或“_”开头(官方规则,避免冲突),则调用 proxy(vm, `_data`, key),作用看如下示例
const vm = new Vue({data: {a: 'aa'}})
这里 vm.a 能取到值,或修改 a 的值,都是通过以上proxy代理实现的,直接去 vm._data 操作。
5:真正处理响应的地方
-
observe(data, true) (src/core/observe/index.js)
img3
创建 Observer 实例并返回
img4
将Observe实例添加到vue实例的 data.__ob__ 上
img5
如上两图,如果data是对象,则遍历各key调用 defineReactive,如果是数组,则递归调用 observe 方法
- 响应式核心代码 defineReactive(obj, keys[i]) (src/core/observe/index.js)
img6
这里可以看出,Vue数据响应式主要是通过 Object.defineProperty(get+set) 来实现的,这里面用到了 Dep,我们先看看 Dep 是什么
src/core/observe/dep.js
img7
Dep类有一个静态属性target,用来存放 watcher;subs用来存放 watcher 数组;depend 方法为 watcher 调用 addDep来存放Dep的实例,notify 为派发更新,将 subs 中存放的 watcher 一个个拿出来调用 update 方法重新设值。由此可知,Dep是配合Watcher来实现依赖收集及更新的。让我们来看看Watcher里面有些什么
src/core/observe/watcher.js
img8
这个类代码有点多,看 addDep 方法,可知watcher的newDeps存放了dep,dep的subs存放了watcher。依赖更新方法 update 调用了 queueWatcher (src/core/observer/scheduler.js)
img9
这里主要是将需要更新的watcher收入队列,待执行。真正执行更新的方法在 nextTick(flushScheduQueue) (src/core/util/next-tick.js)
img10
了解了Dep和Watcher,再来看img6
在获取data属性值时,先判断Dep.target是否有值,有值的话,让watcher关联dep,再就是子对象和数组的处理
看下set
img11
修改值后dep调用notify方法派发更新
写得很乱,dep和watcher的关系还是有点懵!参考下下面这条资料
关于observe、dep、watcher在下篇文章再详细说明吧~
网友评论