Vue2响应式系统之set和delete怎么用(delete,set,vue,开发技术)

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

1、数组集

import{observe}from"./reactive";importWatcherfrom"./watcher";constdata={list:[1,2],};observe(data);constupdateComponent=()=>{console.log(data.list);};newWatcher(updateComponent);list[0]=3;

list[0]会触发 的重新执行吗?updateComponent

可以先思考一下。

答案是否定的,数组我们只能通过重写的 、 等方法去触发更新,详见pushspliceVue2响应式系统之数组。

如果我们想要替换数组某个元素的话可以转一下弯,通过去实现。splice

import{observe}from"./reactive";importWatcherfrom"./watcher";constdata={list:[1,2],};observe(data);constupdateComponent=()=>{console.log(data.list);};newWatcher(updateComponent);//list[0]=3;data.list.splice(0,1,3);

每次这样写太麻烦了,我们可以提供一个方法供用户使用。set

/***Setapropertyonanobject.Addsthenewpropertyand*triggerschangenotificationifthepropertydoesn't*alreadyexist.*/exportfunctionset(target,key,val){if(Array.isArray(target)){target.length=Math.max(target.length,key);target.splice(key,1,val);returnval;}//targe是对象的情况//...}

然后我们直接使用方法就可以了。set

import{observe,set}from"./reactive";importWatcherfrom"./watcher";constdata={list:[1,2],};observe(data);constupdateComponent=()=>{console.log(data.list);};newWatcher(updateComponent);//list[0]=3;//data.list.splice(0,1,3);set(data.list,0,3);

2、数组 del

同数组,我们顺便提供一个的方法,支持数组响应式的删除某个元素。setdel

/***Deleteapropertyandtriggerchangeifnecessary.*/exportfunctiondel(target,key){if(Array.isArray(target)&&isValidArrayIndex(key)){target.splice(key,1);return;}//targe是对象的情况//...}

3、对象 set

import{observe,set,del}from"./reactive";importWatcherfrom"./watcher";constdata={obj:{a:1,b:2,},};observe(data);constupdateComponent=()=>{constc=data.obj.c?data.obj.c:0;console.log(data.obj.a+data.obj.b+c);};newWatcher(updateComponent);data.obj.c=3;

updateComponent方法中虽然使用了的属性,但是在调用之前,中并没有属性,所以属性不是响应式的。objcobservedata.objcc

当我们修改的值的时候,并不会触发的执行。data.obj.cupdateComponent

如果想要变成响应式的话,一种方法就是在最开始就定义属性。c

constdata={obj:{a:1,b:2,c:null,},};observe(data);constupdateComponent=()=>{constc=data.obj.c?data.obj.c:0;console.log(data.obj.a+data.obj.b+c);};newWatcher(updateComponent);data.obj.c=3;

另一种方法就是通过去设置新的属性了,在中我们可以将新添加的属性设置为响应式的。setset

/***Setapropertyonanobject.Addsthenewpropertyand*triggerschangenotificationifthepropertydoesn't*alreadyexist.*/exportfunctionset(target,key,val){if(Array.isArray(target)){target.length=Math.max(target.length,key);target.splice(key,1,val);returnval;}//targe是对象的情况//key在target中已经存在if(keyintarget&&!(keyinObject.prototype)){target[key]=val;returnval;}constob=target.__ob__;//target不是响应式数据if(!ob){target[key]=val;returnval;} //将当前key变为响应式的defineReactive(target,key,val);returnval;}

回到我们之前的程序:

import{observe,set,del}from"./reactive";importWatcherfrom"./watcher";constdata={obj:{a:1,b:2,},};observe(data);constupdateComponent=()=>{constc=data.obj.c?data.obj.c:0;console.log(data.obj.a+data.obj.b+c);};constob=newWatcher(updateComponent);set(data.obj,"c",3);

虽然通过增加了属性,但是此时并不会重新触发,原因的话我们看下依赖图。setWatcher

Vue2响应式系统之set和delete怎么用

虽然属性拥有了对象,但由于没有调用过依赖属性的,所以它并没有收集到依赖。cDepcWatcher

当然我们可以完手动调用一次相应的。setWatcher

constdata={obj:{a:1,b:2,},};observe(data);constupdateComponent=()=>{constc=data.obj.c?data.obj.c:0;console.log(data.obj.a+data.obj.b+c);};constob=newWatcher(updateComponent);set(data.obj,"c",3);ob.update();//手动调用Watcherdata.obj.c=4;

这样的话,当执行的时候就会触发的执行了。data.obj.c = 4Watcher

那么我们能将触发相应的的逻辑放到函数中吗?Watcherset

Vue2响应式系统之set和delete怎么用

可以看到里也有个,这个其实当时是为数组准备的,参考objDepVue2响应式系统之数组,但的什么都没收集。objdep

我们修改一下代码让它也收集一下:

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();if(childOb){ /******新位置*************************/ childOb.dep.depend(); /**********************************/if(Array.isArray(value)){//childOb.dep.depend();//原来的位置dependArray(value);}}}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();},});}functiondependArray(value){for(lete,i=0,l=value.length;i<l;i++){e=value[i]; /******新位置*************************/e&&e.__ob__&&e.__ob__.dep.depend(); /**********************************/if(Array.isArray(e)){//e&&e.__ob__&&e.__ob__.dep.depend();//原位置dependArray(e);}}}

因为读取属性,一定先会读取属性,即。也同理。aobjdata.obj.ab

所以通过上边的修改,的会收集到它的所有属性的依赖,也就是这里的、的依赖,但因为和的依赖是相同的,所以收集到一个依赖。objdepabab

Vue2响应式系统之set和delete怎么用

但其实我们并不知道被哪些依赖,我们只知道和同属于一个对象的和被哪些依赖,但大概率也会被其中的依赖。cWatchercabWatchercWatcher

所以我们可以在中手动执行一下的,依赖的大概率会被执行,相应的也会成功收集到依赖。setobjDepcWatcherc

exportfunctionset(target,key,val){if(Array.isArray(target)){target.length=Math.max(target.length,key);target.splice(key,1,val);returnval;}//targe是对象的情况//key在target中已经存在if(keyintarget&&!(keyinObject.prototype)){target[key]=val;returnval;}constob=target.__ob__;//target不是响应式数据if(!ob){target[key]=val;returnval;}defineReactive(target,key,val);/******新增*************************/ob.dep.notify()/************************************/returnval;}

回到最开始的代码:

constdata={obj:{a:1,b:2,},};observe(data);constupdateComponent=()=>{constc=data.obj.c?data.obj.c:0;console.log(data.obj.a+data.obj.b+c);};constob=newWatcher(updateComponent);set(data.obj,"c",3);

执行完后除了变为响应式的,也成功触发了执行,并且收集到了。cWatcherWatcher

Vue2响应式系统之set和delete怎么用

此时如果修改的值,也会成功触发的执行了。cWatcher

4、对象 del

有了上边的了解,删除就很好解决了。

Vue2响应式系统之set和delete怎么用

如果要删除属性,删除后执行下它相应的就可以。但的是存在闭包中的,我们并不能拿到。aDepaDep

退而求其次,我们可以去执行属性所在的对象的就可以了。aobjDep

/***Deleteapropertyandtriggerchangeifnecessary.*/exportfunctiondel(target,key){if(Array.isArray(target)){target.splice(key,1);return;}//targe是对象的情况constob=target.__ob__;if(!hasOwn(target,key)){return;}deletetarget[key];if(!ob){return;}ob.dep.notify();}
 </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
本文:Vue2响应式系统之set和delete怎么用的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:Vue2响应式系统之怎么让数组生效下一篇:

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

(必须)

(必须,保密)

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