shallowReactive与reactive的原理浅析

vue3中的shallowReactive与reactive是怎么实现的呢?学习自尚硅谷

目的

使一个正常的object对象转化为响应式对象

解决方案

简单的说,就是w3c在object的增删改查时增加了hook函数,可以让用户对原生js获取事件、赋值事件等进行捕捉。这个hook函数就是ProxyReflect.
我接下来做的一件事就是使用这个hook函数,来使一个正常的object对象转化为响应式对象。

严格来讲,这个最后结果还不是响应式对象,只是这个object再增删改查属性的时候会触发自定义逻辑,具体编写什么样的逻辑能能够做到vue3中的响应式,本文没有阐述。

可以首先定义一个事件处理函数,对原生js获取事件、赋值事件等进行捕捉,随后再传递给Reflect

const reactiveHandler = {
  get (target, key) {

    if (key==='_is_reactive') return true
    console.log('数据已获取');

    return Reflect.get(target, key)
  },

  set (target, key, value) {
    const result = Reflect.set(target, key, value)
    console.log('数据已更新, 去更新界面')
    return result
  },

  deleteProperty (target, key) {
    const result = Reflect.deleteProperty(target, key)
    console.log('数据已删除, 去更新界面')
    return result
  },
}

然后就可以进行转化了:

/* 
自定义shallowReactive
目的是让该对象成为一个Proxy对象,方便对一些增删改查的方法进行拦截并添加自定义逻辑
*/
function shallowReactive(obj) {
  return new Proxy(obj, reactiveHandler)
}

/* 
自定义reactive
目的是让该对象,以及该对象内部所有object类型的成员成为一个Proxy对象,方便对一些增删改查的方法进行拦截并添加自定义逻辑
*/
function reactive (target) {
  if (target && typeof target==='object') {
    // 内部代码块的作用是:
      // 1. 遍历子元素,目的是查看子元素中是否存在object,如果存在再次进入子元素;
      // 2. 最终返回一个代理对象Proxy,代理该object

    if (target instanceof Array) { 

      // 检测到是数组
      target.forEach((item, index) => {
        target[index] = reactive(item)
      })

    } else { 

      // 检测到是对象
      Object.keys(target).forEach(key => {
        target[key] = reactive(target[key])
      })

    }
    // 如果这个taraget是一个object,下面的代码是无论如何都会对这个object执行的
    // 换句话说:对每一个子object类型的对象,执行了下面的代码
    const proxy = new Proxy(target, reactiveHandler)
    return proxy
  }

  // 如果不是object,则直接返回
  return target
}







console.log('=================测试自定义shallowReactive');
const proxy = shallowReactive({
  a: {
    b: 3
  }
})

proxy.a = {b: 4} // 劫持到了
proxy.a.b = 5 // 没有劫持到

console.log('=================测试自定义reactive');
/* 测试自定义reactive */
const obj = {
  a: 'abc',
  b: [{x: 1}],
  c: {x: [11]},
}

const proxy2 = reactive(obj)
console.log(proxy2)
proxy2.b[0].x += 1
proxy2.c.x[0] += 1

posted @ 2021-05-26 10:18  Bravo_Jack  阅读(515)  评论(0编辑  收藏  举报