写点什么

【Vue2.x 源码学习】第四篇 - 对象的深层劫持

用户头像
Brave
关注
发布于: 2021 年 06 月 04 日
【Vue2.x 源码学习】第四篇 - 对象的深层劫持

一,前言


上篇,主要介绍了在 Vue 的数据初始化流程中,对象属性的单层劫持是如何实现的

回顾一下,主要涉及以下几个核心点:

  • data 为函数和对象的处理,及当 data 为函数时的 this 指向问题

  • Observer 类:对数据进行观测

  • walk 方法:遍历 data 属性(对象属性遍历)

  • defineReactive 方法:利用 Object.defineProperty 实现数据劫持


本篇,继续对 data 数据进行初始化操作,对象属性的深层劫持


二,对象属性的深层观测问题

1,抛出问题

当前版本的代码逻辑:

如果,data 对象中的属性,还是一个对象(称为 obj)

那么,这个对象(obj)中的属性是不会被观测的(目前所说的观测还仅仅停留在数据劫持阶段)

就是说,当前仅实现了对 data 对象中属性的单层劫持,嵌套对象不会被深层劫持

2,测试问题

<script>  let vm = new Vue({    el: '#app',    data() {      // data函数返回的对象中,obj属性为一个对象,它的属性不会被观测      return { message: 'Hello Vue', obj: { key: "val" } }    }  });</script>
复制代码

3,查看结果

new Vue 时,传如的 options 选项中的 data 函数,

data 函数中,属性 obj 的值依然是一个对象 { key: "val" }

对象 { key: "val" } 中的 key,此时没有被添加 get 和 set 方法,说明 key 没有被劫持


三,对象属性深层观测的实现

1,实现思路


TODO:需要先回顾一下,对象属性单层观测的流程

有了 data 对象单层观测的经验,对象属性 obj 深层劫持就简单多了


当对象属性 obj 即将被 Object.defineProperty 劫持时,

再对 obj 对象做一次“对象的单层劫持”

更深层的对象属性劫持,就是在递归执行“对象的单层劫持”


即:当属性为对象类型时(非 null)

继续调用 observe 进行观测,observe 的递归实现了对象属性的深层劫持

2,代码逻辑


function defineReactive(obj, key, value) {  observe(value);// 递归实现深层观测  Object.defineProperty(obj, key, {    get() {      return value;    },    set(newValue) {      if (newValue === value) return      value = newValue;    }  })}
复制代码

TODO:需要突出递归的逻辑



四,data 相关优化


TODO:结合对象属性观测的特点,介绍 data 的相关优化


五,结尾


又成功水了一篇,还剩 17 篇


本篇主要实现了 Vue 数据初始化流程中,对象属性的深层劫持,核心思路就是递归;


  1. 通过 data = isFunction(data) ? data.call(vm) : data;处理后的 data 一定是对象类型

  2. 通过 data = observe(data)处理后的 data 就实现了数据的响应式(目前只有劫持)

  3. observe 方法最终返回一个 Observer 类

  4. Observer 类初始化时,通过 walk 遍历属性

  5. 对每一个属性进行 defineReactive(Object.defineProperty)就实现对象属性的单层数据劫持

  6. 在 defineReactive 中,如果属性值为对象类型就继续调用 observe 对当前的对象属性进行观测(即递归步骤 3~5),这样就实现了对象属性的深层数据劫持


下一篇,数组的劫持


用户头像

Brave

关注

还未添加个人签名 2018.12.13 加入

还未添加个人简介

评论

发布
暂无评论
【Vue2.x 源码学习】第四篇 - 对象的深层劫持