Vue2响应式系统之深度响应怎么实现(vue,开发技术)

时间:2024-05-09 19:15:10 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

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.textdata.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",},};

Vue2响应式系统之深度响应怎么实现

我们当然不希望每次都赋值整个对象,我们需要做一些修改,把嵌套的对象也变成响应式的。

2、方案

我们只需要在给某个重写和之前,把它的就像上边给调用函数一样,也调用一次函数即可。keygetsetvaluedataobserveobserve

同时提供参数,留下扩展,让外界决定是否需要深度响应。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();},});}

同时,在函数中,传进来的不是对象的话我们直接。observevaluereturn

/*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);,执行一次输出。updateComponenthello

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响应式系统之深度响应怎么实现的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:Vue2响应式系统之嵌套怎么实现下一篇:

8 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18