vue源码解析之data原理

2,362 阅读3分钟

方法执行时机

在beforeCreate之后,created之前,会initState initState中会调用initData

源码分析

initData

上面代码主要做了三件事:

  1. 判断 data 对象的每一个 key,不可以和 props、methods 中的 key 相同。否则会报警告。可以看出优先级是 methods > props > data;
  2. 给data设置代理,代理vm._data到vm上,就可以通过this.xxx访问_data上的属性了;
  3. 观测data;

proxy

给data设置代理 data有个暗箱操作,就是访问转移,你用this.xxx访问data时,实际上访问的是this._data.xxx;

  1. 使用 data 在 vm 上占位,使得可以通过 vm.xxx 的形式访问到 data;
  2. 设置 Object.defineProperty的 get 和 set ,间接获取和赋值 vm._data,所有对 data的操作,转接到 vm._data 上;

observe

  1. 函数返回ob,ob就是Observer的实例,是通过data初始化的;
  2. data 必须是对象或数组;
  3. 如果 value 是数组或普通对象且可继承,则用它来初始化一个 Observer 实例;
  4. 如果 data 有__ob__属性,并且__ob_属性引用的是 Observer 的实例,则ob = value._ob
  5. __ob__这个属性是在初始化 Observer 实例的时候加上的。有了这个属性就表示这个对象被观测过;

new Observer(value)这里面具体做了什么呢? 先看 constructor,做了几件事:

  1. 把 data 自身赋值到 observer 实例的 value 属性;
  2. 生成一个 dep 对象,赋值到 observer 实例的 dep 属性;
  3. 给自身添加一个__ob__属性,引用 observer 实例;
  4. 如果 value 是对象,就调用walk(value)方法遍历这个对象的属性;
  5. 如果 value 是数组,就调用observeArray(value)方法,观测数组的每个元素;
  6. 对于数组,需要拦截对数组的变异方法,当数组元素改变的时候,可以触发对应的依赖。protoAugment和copyAugment就是做这样的事。 observeArray(value)方法会遍历数组中的每一项,执行observe(items[i]),对每一项进行观测。 walk(value)方法遍历这个对象的属性,对每个属性调用defineReactive(obj, keys[i]),设置其 getter 和 setter 方法;

vue系列课程

最近会陆续的对vue进行源码分析,一系列课程如下:

state系列

  1. props原理
  2. methods原理
  3. data原理
  4. computed原理
  5. watch原理

lifecycle系列

  1. 生命周期原理

event系列

  1. event原理

render系列

  1. render原理

inject/provide系列

  1. inject/provide原理

plugins系列

  1. vue-router原理
  2. Vue Router 那些事
  3. Vuex你应该知道的事
  4. vue源码解析之vuex原理
  5. Vue自定义插件

组件系列

  1. keep-alive原理
  2. Vue 单文件组件
  3. Vue组件间通信
  4. vue虚拟列表

指令系列

  1. Vue自定义指令
  2. vue源码解析之Directives原理

算法系列

  1. diff原理
  2. Vue编译器源码分析

异步任务

  1. vue源码解析之NextTick原理

其他

  1. vue单元测试
  2. Vue轮播组件
  3. 你不知道的vue那些事
  4. vue技巧大解密
  5. 面试-高级前端之VUE数据响应式实现