Proxy实现监听
之前分享过vue2的响应式,然后有人问vue3用proxy是怎么实现的,本来打算研究一波,看了源码之后,发现自己想多了,所以改成学一学proxy的使用。
想看源码的可以去git上面下载:
https://github.com/vuejs/vue-next
然后主要代码是在这两个目录下,而且都是用ts写的:
packages/reactivity下面的reactive和baseHandlers
Proxy之前有稍微过一遍,在ES6目录里面,支持13种拦截。然后返回对象的值使用了Reflext,主要是为了将Object对象一些明显属于语言内部的方法放到Reflect对象上。之前也有过一遍。
然后大概简单使用:
let obj = {
msg: {
a: 10
},
arr: [1, 2, 3]
}
let handler = {
get(target, key){
console.log('get', target, key);
//懒监听,去获取的时候才监听对象里面的对象,而不是直接递归循环监听
if(typeof target[key] === 'object' && target[key] !== null){
return new Proxy(target[key], handler);
}
return Reflect.get(target, key);
},
set(target, key, value){
console.log('set', target, key, value);
//数组新增会执行两次,一次是修改length,一次是添加值
let oldValue = target[key];
if(!oldValue){
//找不到老值,新增
}else if(oldValue !== value){
//老值和新值不相等,修改
}
return Reflect.set(target, key, value);
}
}
let proxy = new Proxy(obj, handler)
proxy.arr.push(4);
proxy.msg.a = 50;
proxy.msg.b = 60;
proxy.c = 70;
相比较起来,defineProperty无法一次性监听所有属性,必须遍历或者递归,而且无法监听新增的属性。对于数组,defineProperty需要劫持数组方法,进行函数劫持。对于上面的问题,Proxy都支持。运行上面的方法,可以试试是不是都可以。
Proxy拦截的还很多,要不是兼容性问题,我觉得defineProperty会被取代。Proxy能做的还有很多,不过平常是用不上了,要是开发一些工具库绝对是很好的选择。
image
发表评论 (审核通过后显示评论):