vue3 reactive响应式原理的简单理解和实现

1,022 阅读1分钟

vue3 reactive响应式原理的简单理解和实现

主要思路

  1. 利用 Proxy 代理对象。
  2. 当 get 的时候才递归,不像 vue2 一开始就递归到底。
  3. set 的时候 通过 ownKeys 判断是新增属性还是修改属性。

代码

function reactive(target = {}) {
  if (typeof target !== 'object' || target == null) {
    // 不是对象或者数组直接返回
    return target
  }

  // 代理配置
  const handler = {
    get(target, key, receiver) {
      const ownKeys = Reflect.ownKeys(target)
      //  只处理本身(非原型) 属性---原型的属性例如:push
      if (ownKeys.includes(key)) {
        console.log('get', key)
      }

      const result = Reflect.get(target, key, receiver)
      return reactive(result) // 递归调用实现深度监听
      // 性能如何提升的?
      // 当 get 的时候才递归,不像 vue2 一开始就递归到底
    },
    set(target, key, val, receiver) {
      // 重复的数据或值没有改变不处理
      // 场景:
      // 1. 数组push()的时候,length不用重设;
      // 2. proxyTom.age 已经是 18 再执行  proxyTom.age = 18
      const oldVal = target[key]
      if (val === oldVal) { return true }

      // 判断是新增属性还是修改属性
      const ownKeys = Reflect.ownKeys(target)
      if (ownKeys.includes(key)) {
        console.log('set 修改属性---', key, val)
      } else {
        console.log('set 新增属性---', key, val)
      }

      const result = Reflect.set(target, key, val, receiver)
      console.log('result---', result)
      return result // 是否设置成功 true:成功,false:失败
    },
    deleteProperty(target, key, receiver) {
      const result = Reflect.deleteProperty(target, key)
      console.log('deleteProperty', key)
      console.log('result---', result)
      return result  // 是否删除成功 true:成功,false:失败
    }
  }

  // new 代理对象
  const observed = new Proxy(target, handler)

  return observed
}

const Tom = {
  name: 'Tom',
  age: 18,
  male: 'boy',
  friend: {
    name: 'Jack',
    age: 10,
  }
}

const proxyTom = reactive(Tom)
proxyTom.friend.name

console.log('%c------------------------', 'color:blue')

proxyTom.test = {}

console.log('%c------------------------', 'color:blue')

proxyTom.test.test = 0

console.log('%c------------------------', 'color:blue')

proxyTom.aaa.aaa = 0 // 不生效
console.log(Tom)
    

相关