Vue2响应式系统之深度响应怎么实现
导读:本文共2897.5字符,通常情况下阅读需要10分钟。同时您也可以点击右侧朗读,来听本文内容。按键盘←(左) →(右) 方向键可以翻页。
摘要: 1、场景import{observe}from"./reactive";importWatcherfrom"./watcher";constdata={text:{innerText:{childText:"hello",},},};observe(data);constupdate... ...
目录
(为您整理了一些要点),点击可以直达。1、场景
import{observe}from"./reactive";importWatcherfrom"./watcher";constdata={text:{innerText:{childText:"hello",},},};observe(data);constupdateComponent=()=>{console.log(data.text.innerText.childText);};newWatcher(updateComponent);data.text.innerText.childText="liang";
我们的响应式系统到现在还没有支持属性是对象时候的响应,因此我们改变的时候不会有任何输出。childText
我们只收集了的依赖,所以如果想要响应的话必须给整个赋值为一个新对象。data.text
data.text
import{observe}from"./reactive";importWatcherfrom"./watcher";constdata={text:{innerText:{childText:"hello",},},};observe(data);constupdateComponent=()=>{console.log(data.text.innerText.childText);};newWatcher(updateComponent);data.text={innerText:{childText:"liang",},};
我们当然不希望每次都赋值整个对象,我们需要做一些修改,把嵌套的对象也变成响应式的。
2、方案
我们只需要在给某个重写和之前,把它的就像上边给调用函数一样,也调用一次函数即可。key
get
set
value
data
observe
observe
同时提供参数,留下扩展,让外界决定是否需要深度响应。shallow
/*******************新增shallow*******************/exportfunctiondefineReactive(obj,key,val,shallow){/****************************************************/constproperty=Object.getOwnPropertyDescriptor(obj,key);//读取用户可能自己定义了的get、setconstgetter=property&&property.get;constsetter=property&&property.set;//val没有传进来话进行手动赋值if((!getter||setter)&&arguments.length===2){val=obj[key];}constdep=newDep();//持有一个Dep对象,用来保存所有依赖于该变量的Watcher/*******************新增****************************/!shallow&&observe(val); /******************************************************/Object.defineProperty(obj,key,{enumerable:true,configurable:true,get:functionreactiveGetter(){constvalue=getter?getter.call(obj):val;if(Dep.target){dep.depend();}returnvalue;},set:functionreactiveSetter(newVal){constvalue=getter?getter.call(obj):val;if(setter){setter.call(obj,newVal);}else{val=newVal;}dep.notify();},});}
同时,在函数中,传进来的不是对象的话我们直接。observe
value
return
/*util.jsexportfunctionisObject(obj){returnobj!==null&&typeofobj==="object";}*/exportfunctionobserve(value){if(!isObject(value)){return;}letob=newObserver(value);returnob;}
3、场景2
import{observe}from"./reactive";importWatcherfrom"./watcher";constdata={text:{innerText:{childText:"hello",},},};observe(data);constupdateComponent=()=>{console.log(data.text.innerText.childText);};newWatcher(updateComponent);data.text.innerText.childText="liang";data.text={innerText:{childText:"liang2",},};data.text.innerText.childText="liang3";
可以一分钟想一下上边会输出什么。
new Watcher(updateComponent);
,执行一次输出。updateComponent
hello
data.text.innerText.childText = "liang";
,我们已经解决了属性是对象的情况,因此这里也会输出。liang
data.text={innerText:{childText:"liang2",},};
上边代码就是文章最开头的方法,因此也会触发函数执行,输出。liang2
data.text.innerText.childText = "liang3";
最后这句会执行吗?
答案是否定的了,因为我们的赋值为了一个新对象,但这个新对象我们并没有将其设置为响应式的。data.text
因此我们需要在的时候把对象也设置为响应式的。set
/***DefineareactivepropertyonanObject.*/exportfunctiondefineReactive(obj,key,val,shallow){constproperty=Object.getOwnPropertyDescriptor(obj,key);//读取用户可能自己定义了的get、setconstgetter=property&&property.get;constsetter=property&&property.set;//val没有传进来话进行手动赋值if((!getter||setter)&&arguments.length===2){val=obj[key];}constdep=newDep();//持有一个Dep对象,用来保存所有依赖于该变量的WatcherletchildOb=!shallow&&observe(val);Object.defineProperty(obj,key,{enumerable:true,configurable:true,get:functionreactiveGetter(){constvalue=getter?getter.call(obj):val;if(Dep.target){dep.depend();}returnvalue;},set:functionreactiveSetter(newVal){constvalue=getter?getter.call(obj):val;if(setter){setter.call(obj,newVal);}else{val=newVal;}/******新增*************************/childOb=!shallow&&observe(newVal);/************************************/dep.notify();},});}
</div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
Vue2响应式系统之深度响应怎么实现的详细内容,希望对您有所帮助,信息来源于网络。