通过学会Proxy代理的用法彻底理解vue3响应式原理思路,附带对比vue2响应式原理
背景:
最近写了通过学会Object.defineProperty的用法理解vue2响应式原理的文章。,所以就最近抽空把vue3的一起做了,通过对比vue2和vue3响应式原理的变化肯定理解上会更直观。
Proxy的作用简述:
Proxy是ES6 中新增的一个函数,也可以叫类, Proxy 其实就是一种构造器,所以要通过new关键字实现的,从作用上讲,也是一种拦截器在设置对象属性或者读取对象属性时做一层拦截操作。
先说一个注意事项:Proxy没有原型对象 由于Proxy构造出来的实例对象是对目标对象的一个代理,因此Proxy在构造过程中是不需要prototype进行初始化的,因为其他构造函数之所以需要 prototype,是因为构造出来的对象需要一些初始化的成员,所以将这些成员定义到了 protoype 上,Proxy 只是用来代理其他对象,所以本身不需要prototype。
Proxy用法:
基本语法是:new Proxy(target, handler);
其中第一个参数target为被代理对象,第二个参数handler为做拦截需要做什么操作即set、get等方法。 其中第二个参数包含众多方法,例如:
handler.getPrototypeOf() // 在读取代理对象的原型时触发该操作
handler.setPrototypeOf() // 在设置代理对象的原型时触发该操作
handler.isExtensible() // 在判断一个代理对象是否是可扩展时触发该操作
handler.preventExtensions() // 在让一个代理对象不可扩展时触发该操作
handler.getOwnPropertyDescriptor() // 在获取代理对象某个属性的属性描述时触发该操作
andler.defineProperty() // 在定义代理对象某个属性时的属性描述时触发该操作
handler.has() // 在判断代理对象是否拥有某个属性时触发该操作
handler.get() // 在读取代理对象的某个属性时触发该操作
handler.set() // 在给代理对象的某个属性赋值时触发该操作
handler.deleteProperty() // 在删除代理对象的某个属性时触发该操作
handler.ownKeys() // 在获取代理对象的所有属性键时触发该操作
handler.apply() // 在调用一个目标对象为函数的代理对象时触发该操作
handler.construct() // 在给一个目标对象为构造函数的代理对象构造实例时触发该操作
重点来了,我们理解vue3响应式原理思路主要通过get和set就行:
get方法有三个参数get(target, key, proxy)分别为目标对象、键、实例对象本身
set方法有四个参数 set(target, key, value, proxy),分别为目标对象、键、值、实例对象本身。
var testobj = new Proxy({name:'lxp'},{
get(target,key,value,proxy){
console.log('触发get')
},
set(target,key,value,proxy){
console.log('触发set')
}
});
testobj.name = '天天啊';//当设置对象属性值,打印'触发set'
testobj.name;//当获取对象,打印'触发get'
当然,既然拦截了内容肯定就是要做一些操作了,例如我想要返回拦截的实际值,直接用通过对象和键就能获取到
get (target, key, value, proxy) {
return target[key]
}
小结一下:
如上代码例子所示,proxy对整个对象进行了拦截,只要获取里面的属性内容就会触发get方法,设置对象就触发set方法。
所以对比vue2的Object.defineProperty递归去拦截对象所有属性,Proxy是对整个对象进行拦截的,所以解决了vue2对数组下标无法监听的问题,这也是vue3使用Proxy而放弃了Object.defineProperty的根本原因。
转载自:https://juejin.cn/post/7352079427864018955