shallowReadonly 与 readonly原理浅析

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

目的

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

解决方案

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

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

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

const readonlyHandler = {
  get (target, key) {
    if (key==='_is_readonly') return true

    return Reflect.get(target, key)
  },

  set () {
    console.warn('只读的, 不能修改')
    return true
  },

  deleteProperty () {
    console.warn('只读的, 不能删除')
    return true
  },
}

/* 
自定义shallowReadonly
*/
function shallowReadonly(obj) {
  return new Proxy(obj, readonlyHandler)
}

/* 
自定义readonly
*/
function readonly(target) {
  if (target && typeof target==='object') {
    if (target instanceof Array) { // 数组
      target.forEach((item, index) => {
        target[index] = readonly(item)
      })
    } else { // 对象
      Object.keys(target).forEach(key => {
        target[key] = readonly(target[key])
      })
    }
    const proxy = new Proxy(target, readonlyHandler)

    return proxy 
  }

  return target
}

/* 测试自定义readonly */
/* 测试自定义shallowReadonly */
const objReadOnly = readonly({
  a: {
    b: 1
  }
})
const objReadOnly2 = shallowReadonly({
  a: {
    b: 1
  }
})

objReadOnly.a = 1
objReadOnly.a.b = 2
objReadOnly2.a = 1
objReadOnly2.a.b = 2
posted @ 2021-05-25 21:51  Bravo_Jack  阅读(160)  评论(0编辑  收藏  举报