浅析Proxy可以优化vue的数据监听机制问题及实现思路
我们首先来看vue2.x中的实现,为简单起见,我们这里不考虑多级嵌套,也不考虑数组
vue2.x中的实现
其本质是newWatcher(data,key,callback)的方式,而在调用之前是先将data中的所有属性转化成可监听的对象,其主要就是利用Object.defineProperty,。
classWatcher{
constructor(data,key,cb){
}
}
//转换成可监听对象
functionobserve(data){
newObserver(data)
}
//修改数据的getter和setter
functiondefineReactive(obj,key){
letvalue=obj[key];
Object.defineProperty(obj,key,{
enumerable:true,
configurable:true,
get(){
returnvalue;
},
set(newVal){
value=newVal
}
})
}
Observer的实现很简单
classObserver{
constructor(data){
this.walk(data);
}
walk(data){
for(varkeyindata){
//这里不考虑嵌套的问题,否则的话需要递归调用walk
defineReactive(data,key)
}
}
}
现在怎么将watcher和getter/setter联系起来,vue的方法是添加一个依赖类:Dep
classWatcher{
constructor(data,key,cb){
this.cb=cb;
Dep.target=this;//每次新建watcher的时候讲给target赋值,对target的管理这里简化了vue的实现
data[key];//调用getter,执行addSub,将target传入对应的dep;vue的实现本质就是如此
}
}
classDep{
constructor(){
this.subs=[];
}
addSub(sub){
this.subs.push(sub);
}
notify(){
this.subs.forEach(sub=>sub.cb())
}
}
functiondefineReactive(obj,key){
letvalue=obj[key];
letdep=newDep();//每一个属性都有一个对应的dep,作为闭包保存
Object.defineProperty(obj,key,{
enumerable:true,
configurable:true,
get(){
dep.addSub(Dep.target)
Dep.target=null;
returnvalue;
},
set(newVal){
value=newVal
dep.notify();
}
})
}
以上就是vue的思路,vue3之所以要从新实现,主要有这几个原因:
- Object.defineProperty的性能开销。
- defineReactive一开始就要对要监听的对象所有属性都执行一遍,因为传统方法要将一个对象转换成可监听对象,只能如此。
- 添加删除属性的问题。
- 还有一点就是这个模块被耦合到了vue里面,新版本可以单独作为一个库来使用。
然后我们来看看同样的功能采用Proxy会怎样实现。
Proxy的实现
将一个对象转换成Proxy的方式很简单,只需要作为参数传给proxy即可;
classWatcher{
constructor(proxy,key,cb){
this.cb=cb;
Dep.target=this;
this.value=proxy[key];
}
}
classDep{
constructor(){
this.subs=[]
}
addSub(sub){
this.subs.push(sub);
}
notify(newVal){
this.subs.forEach(sub=>{
sub.cb(newVal,sub.value);
sub.value=newVal;
})
}
}
constobserve=(obj)=>{
constdeps={};
returnnewProxy(obj,{
get:function(target,key,receiver){
constdep=(deps[key]=deps[key]||newDep);
Dep.target&&dep.addSub(Dep.target)
Dep.target=null;
returnReflect.get(target,key,receiver);
},
set:function(target,key,value,receiver){
constdep=(deps[key]=deps[key]||newDep);
Promise.resolve().then(()=>{
dep.notify(value);
})
returnReflect.set(target,key,value,receiver);
}
});
}
varstate=observe({x:0})
newWatcher(state,'x',function(n,o){
console.log(n,o)
});
newWatcher(state,'y',function(n,o){
console.log(n,o)
});
state.x=3;
state.y=3;
也许一开始我们只关心x和y,那么就不会对其他的属性做相应的处理,除非添加watcher,其他时间target都是null
总结
以上所述是小编给大家介绍的Proxy可以优化vue的数据监听机制问题,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!