You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
function reactiveGetter () {
const value = getter ? getter.call(obj) : val
if (Dep.target) {
dep.depend()
if (childOb) {
childOb.dep.depend()
if (Array.isArray(value)) {
dependArray(value)
}
}
}
return value
}
正文
入口observe
Observe对外只暴露了一个函数observe,Observer类虽然给了export,但是外部并无调用。
上面就是observe函数的源代码;
此函数作为监听的入口文件,对数据进行拦截判断,返回一个Observer的实例。
类Observer
Observer是一个class,有三个私有属性:value、dep、vmCount;一起来看下其构造函数:
构造函数干了四件事情:
上面讲到的【支持__proto__属性】,现在主流浏览器都支持的,除了IE;
数组处理
protoAugment和copyAugment方法的参数,参数差别就是最后一个参数arrayKeys;
上面会对arrayMethods里面的值进行重新定义,也就是重写会引起数组变化的方法,以达到对数组进行监听的目的。
接下来,咱们分别看下两个方法(protoAugment和copyAugment)的实现:
copyAugment方法,因为不支持__proto__的缘故,则需要在数组上面覆盖原生的arrayMethods里面的方法,也就达到了对数组进行监听的目的。
数组走observeArray
observeArray非常简单:
循环调用上面文章开头介绍的observe方法;最终都会走到下面要说的walk方法。
非数组走walk
walk函数也是非常简单:
获取到当前对象的keys后,对keys进行遍历,遍历调用defineReactive,传递两个参数,参数1为当前对象,参数2为当前遍历到的key。
defineReactive
接下来是重头戏,这才是Vue真正的核心之一。来看下defineReactive的源码:
先说下调用defineReactive的地方:
接着说下defineReactive函数的参数:
不用看着defineReactive很长,其实就干了三件事情,一一来看
defineReactive源码解读:
然后咱们接下来看下重新声明后get的定义:
上面代码是重新定义的get方法,先是调用原生getter方法获取到value,然后判断是否有Dep.target,Dep.target是一个Watcher对象,然后调用收集依赖的函数dep.depend(),然后依次判断childOb,收集依赖;每次调用defineReactive,都有一个唯一的Dep实例与当前value一一对应。
上面代码是重新定义的set方法,先是调用原生getter方法获取到value,然后对newVal进行判断,如果未发生变化则直接返回;
如果只有getter没有setter则直接返回;然后调用原生setter进行赋值,后面调用dep.notify进行通知更新;notify会调用dep对象下面所有的依赖watcher对象下面的update方法进行更新操作;下面咱们会讲到Dep。
Dep
上面讲到了Dep的使用,现在咱们来看下Dep的实现。
上面代码就是去除生产环境后的代码。
可以看到Dep对象有三个变量:一个是target,target对象是一个Watcher对象,同时是一个static的对象;id为一个数字的变量;subs则为一个Watcher对象的数组;
额外要讲的是,除了Dep的声明外,还有Dep.target这个static类型的变量的处理:
此处会对Dep.target进行赋值等操作,pushTarget和popTarget是成对出现的,有一个pushTarget则必然有一个popTarget;target则依旧是一个Watcher;暴露给外部调用,收集Watcher所使用,下次咱们会讲到Watcher。
结言
本章沿着observe函数进行了一步步的探索,从Observer到Dep.
The text was updated successfully, but these errors were encountered: