Vue源码窥探之响应式对象

在 Vue 初始化阶段的时候,会执行 _init 方法,其中在 _init 方法中会执行 initState 方法。在 initState 方法中,我们会对 propsmethodsdatacomputedwatch 进行初始化。在我们这篇文章中,主要分析的是 Vue 的数据的响应式,所以我们着重分析 propsdata
Vue源码窥探之响应式对象_第1张图片
首先,我们来看一下 initProps 过程。
Vue源码窥探之响应式对象_第2张图片
initProps 其实就做了两件事,遍历 props ,然后调用 defineReactive 方法把每一个 prop 对应的值变成响应式,可以通过 vm._props.xx 访问到定义 props 中对应的属性。然后我们看看 initData 做了什么。
Vue源码窥探之响应式对象_第3张图片
遍历 data 上的值,先做合法性检测,然后调用 observe 来观察整个 data,很明显 observe 的内部还是会调用 defineReactive 方法的。
Vue源码窥探之响应式对象_第4张图片
我们可以看到,observe 非常简单,如果没有 __ob__ 属性,就实例化一个 Observer ,如果有就直接返回 ob 即可。所以问题关键是 Observer 中发生了什么。
Vue源码窥探之响应式对象_第5张图片
Observer 的构造函数也很简单,实例化了一个 Dep 对象,然后把自身实例添加到对象 value 的 __ob__ 的属性上,该属性不可枚举。最后判断 value ,如果是数组就调用 observeArray 方法,否则就调用 walk 方法。 因为 defineReactive 是对对象上的属性进行响应式,所以 walk 方法就是遍历分别对每一个属性执行 definedReactive 方法即可,而 observeArray 因为是 Array,里面的每一项可能是 object,所以是要分别执行 observe 方法。

我们接着来看一下 definedReactive 的实现,它的主要功能就是把对象中的属性变成响应式。
Vue源码窥探之响应式对象_第6张图片
该方法先初始化了一个 Dep 的实例,接着拿到 obj 的属性描述符,然后对子对象递归调用 observe 方法,这样就保证了无论 obj 结构多复杂,都能够对其属性的每一项及其子属性变成响应式对象,这样我们访问或修改 obj 中一个嵌套层级比较深的属性,也能够触发 getter 和 setter。最后利用 Object.defineProperty 去给 obj 的属性 key 添加 getter 和 setter。其中 getter 做的就是依赖收集,setter 做的就是派发更新。

你可能感兴趣的:(js,vue)