Vue3 响应式原理

响应式原理

Vue中的响应式通过三种响应式解决方案,defineProperty、Proxy、value setter。

Vue2中使用 defineProperty API 实现响应式,存在的缺陷就是删除 obj.count 属性,set 函数不会执行,所以Vue2中需要使用 $delete 函数区删除数据。如下代码实现了简易的响应式功能,定义一个对象obj,使用 defineProperty 代理了 count 属性。这就实现了 obj 对象的 value 属性实现了拦截,读取 count 属性的时候执行 get 函数,修改 count 属性的时候 set 函数,并在 set 函数内部重新计算了 double 。

let getDouble = n=>n*2
let obj = {}
let count = 1
let double = getDouble(count)

Object.defineProperty(obj,'count',{
  get(){
    return count
  },
  set(val){
    count = val
    double = getDouble(val)
  }
})
console.log(double) // 2
obj.count = 2
console.log(double) // 4

Vue3 的响应式机制是基于 Proxy 实现的,解决了 Vue2 响应式的缺陷。如以下代码, 通过 new Proxy 代理了 obj 对象,然后通过 get、set、deleteProperty 函数代理了对象的读取、修改和删除操作,从而实现了响应式的功能。

let getDouble = n=>n*2
let obj = {}
let count = 1
let double = getDouble(count)

let proxy = new Proxy(obj, {
  get : function (target, prop) {
    return target[prop]
  },
  set : function (target, prop, value) {
    target[prop] = value;
    if(prop === 'count') {
      double = getDouble(value)
    }
  },
  deleteProperty(target, prop) {
    delete target[prop]
    if(prop === 'count') {
      double = NaN
    }
  }
})
console.log(obj.count, double) // undefined 2
proxy.count = 2
console.log(obj.count, double) // 2 4
delete proxy.count
console.log(obj.count, double) // undefined NaN

Vue3 Proxy 实现的功能和 Vue2 的 definePropery 类似,都能够在用户修改数据的时候出发 set 函数,更新 double ,Proxy 还完善了 definePropery 的缺陷,如监听属性的删除。Proxy 是针对对象来监听,而不是针对某个具体属性,所以不仅可以代理定义时不存在的属性,还可以代理更丰富的数据结构,比如 Map、Set ...,还能通过 deleteProperty 实现对删除操作的代理。

Vue3 除了 Proxy 还有另一个响应式实现的逻辑,利用对象的 get 和 set 函数来进行监听,这种响应式的实现方式,只能拦截某一个属性的修改,这也是 Vue3 中 ref 这个 API 实现的。如下代码中,拦截了 count 的value 属性,并且拦截了 set 操作,也能实现类似的功能。

let getDouble = n=>n*2
let _value = 1
double = getDouble(_value)

let count = {
  get value() {
    return _value
  },
  set value(val) {
    _value = val
    double = getDouble(_value)
  }
}
console.log(count.value, double) // 1 2
count.value = 2
console.log(count.value, double) // 2 4

这三种实现原理对比如下:

实现原理 defineProperty Proxy value setter
实际场景 Vue2 响应式 Vue3 reactive Vue3 ref
优势 兼容性 基于Proxy实现真正的拦截 实现简单
劣势 数组和属性删除等拦截不了 不兼容IE11 只拦截了value属性
实际应用 Vue2 Vue3 复杂数据结构 Vue3 简单数据结构

你可能感兴趣的:(Vue,前端,JavaScript,javascript,前端,vue,vue.js)