Vue原理解析(六):理解响应式原理-对象

上一篇 Vue 原理解析(五): 虚拟Dom到真实Dom的生成过程

vue 之所以能数据驱动视图发生变更的关键就是:依赖它的响应式系统了。 响应式系统如果根据数据类型区分: 对象和数组两者的实现会有所不同。 解释响应式原理,需要从整体流程出发, 不在vue 组件化的整体流程中找到响应式原理的位置,对深刻理解响应式原理不太好。 接下来我们从整体流程出发, 试着站在巨人的肩膀上分别说明对象和数组的实现原理。

对象的响应式原理

对象响应式数据的创建

  • 在数组的初始化阶段, 将对传入的状态进行初始化, 以下以data为例, 会将传入数据包装为响应式的数据。
对象示例:

main.js
new Vue({  // 根组件
  render: h => h(App)
})

---------------------------------------------------

app.vue
<template>
  <div>{
  {info.name}}</div>  // 只用了info.name属性
</template>
export default {  // app组件
  data() {
    return {
      info: {
        name: 'cc',
        sex: 'man'  //  **即使是响应式数据,没被使用就不会进行依赖收集**
      }
    }
  }
}

接下来的分析将以上面代码为例, 这种结构其实是一个嵌套组件,只不过根组件一般定义的参数比较少而已,理解这个很重要的。

在组件=new Vue() 后执行vm._init() 初始化过程中, 当执行到initState(vm)时就会对内部使用到的一些状态, 如: props, data, computed, watch, methods 分别进行初始化, 再对data 进行初始化的最后有这么一句:

function initData(vm) {  //初始化data
  ...
  observe(data) //  info:{name:'cc',sex:'man'}
}

这个observer 就是将用户定义的data变成响应式的数据, 接下来看看它的创建过程:

export function observe(value) {
  if(!isObject(value)) {  // 不是数组或对象,再见
    return
  }
  return new Observer(value)
}

简单理解这个observer 方法就是Observer 这个类的工厂方法, 所以还是要看下Observer 这个类的定义:

export class Observer {
  constructor(value) {
    this.value = value
    this.walk(value)  // 遍历value
  }
  
  walk(obj) {
    const keys = Object.keys(obj)
    for(let i = 0; i < keys.length; i++) {
      defineReactive(obj, keys[i])  // 只传入了两个参数
    }
  }
}

当执行new Observer 时, 首先将传入的对象挂载到当前this 下, 然后遍历当前对象的每一项, 执行defineReactive 这个方法, 看看它的定义:

export function defineReactive(obj, key, val) {

  const dep = new Dep()  // 依赖管理器
  
  val = obj[key]  // 计算出对应key的值
  observe(val)  // 递归包装对象的嵌套属性
  
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get() {
      ... 收集依赖
    },
    set(newVal) {
      ... 派发更新
    }
  })
}

这个方法的作用就是使用Object.defineProperty创建响应式数据。 首先根据传入的objkey 计算出 val 具体的值; 如果val 还是对象, 那就使用observe 方法进行递归创建, 在递归的过程中使用Object.defindeProperty 将对象的每一个属性都变成响应式数据:

...
data() {
  return {
    info: {
      name: 'cc',
      sex: 'man'
    } 
  }
}
这段代码就会有三个响应式数据:
  info, info.name, info.sex
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值