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

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

1、场景

在开发中肯定存在组件嵌套组件的情况,类似于下边的样子。Vue

<!--parent-component--><div><my-component:text="inner"></my-component>{{text}}<div><!--my-component--><div>{{text}}</div>

回到我们之前的响应式系统,模拟一下上边的情况:

import{observe}from"./reactive";importWatcherfrom"./watcher";constdata={text:"hello,world",inner:"内部",};observe(data);constupdateMyComponent=()=>{console.log("子组件收到:",data.inner);};constupdateParentComponent=()=>{newWatcher(updateMyComponent);console.log("父组件收到:",data.text);};newWatcher(updateParentComponent);data.text="hello,liang";

可以先分钟考虑一下上边输出什么?1

首先回忆一下会做什么操作。new Watcher

第一步是保存当前函数,然后执行当前函数前将全局的赋值为当前对象。Dep.targetWatcher

Vue2响应式系统之嵌套怎么实现

接下来执行函数的时候,如果读取了相应的属性就会触发,从而将当前收集到该属性的中。gettergetWatcherDep

Vue2响应式系统之嵌套怎么实现

2、执行过程

import{observe}from"./reactive";importWatcherfrom"./watcher";constdata={text:"hello,world",inner:"内部",};observe(data);constupdateMyComponent=()=>{console.log("子组件收到:",data.inner);};constupdateParentComponent=()=>{newWatcher(updateMyComponent);console.log("父组件收到:",data.text);};newWatcher(updateParentComponent);data.text="hello,liang";

我们再一步一步理清一下:

  • new Watcher(updateParentComponent);

将赋值为保存了函数的。Dep.targetupdateParentComponentWatcher

接下来执行函数。updateParentComponent

  • new Watcher(updateMyComponent);

将赋值为保存了函数的。Dep.targetupdateMyComponentWatcher

接下来执行函数。updateMyComponent

constupdateMyComponent=()=>{console.log("子组件收到:",data.inner);};//读取了inner变量。//data.inner的Dep收集当前Watcher(保存了`updateMyComponent`函数)
constupdateParentComponent=()=>{newWatcher(updateMyComponent);console.log("父组件收到:",data.text);};//读取了text变量。//data.text的Dep收集当前Watcher(保存了`updateMyComponent`函数)

data.text = "hello, liang";

触发的函数,执行它依赖的,而此时是函数。textsetWatcherupdateMyComponent

所以上边代码最终输出的结果是:

子组件收到: 内部 // new Watcher(updateMyComponent); 时候输出
父组件收到: hello, world // new Watcher(updateParentComponent); 时候输出
子组件收到: 内部 // data.text = "hello, liang"; 输出

然而子组件并不依赖,依赖的父组件反而没有执行。data.textdata.text

3、修复

上边的问题出在我们保存当前正在执行时候使用的是单个变量。WatcherDep.target = null; // 静态变量,全局唯一

回忆一下学习语言或者汇编语言的时候对函数参数的处理:C

functionb(p){console.log(p);}functiona(p){b("child");console.log(p);}a("parent");

当函数发生嵌套调用的时候,执行函数的时候我们会先将参数压入栈中,然后执行函数,同样将参数压入栈中,函数执行完毕就将参数出栈。此时回到函数就能正确取到参数的值了。abbap

对应于的收集,我们同样可以使用一个栈来保存,执行函数前将压入栈,执行函数完毕后将弹出栈即可。其中,始终指向栈顶,代表当前正在执行的函数。WatcherWatcherWatcherDep.targetWatcher

回到代码中,我们提供一个压栈和出栈的方法。Dep

import{remove}from"./util";letuid=0;exportdefaultclassDep{...省略}Dep.target=null;//静态变量,全局唯一//Thecurrenttargetwatcherbeingevaluated.//Thisisgloballyuniquebecauseonlyonewatcher//canbeevaluatedatatime.consttargetStack=[];exportfunctionpushTarget(target){targetStack.push(target);Dep.target=target;}exportfunctionpopTarget(){targetStack.pop();Dep.target=targetStack[targetStack.length-1];//赋值为栈顶元素}

然后中,执行函数之前进行入栈,执行后进行出栈。Watcher

import{pushTarget,popTarget}from"./dep";exportdefaultclassWatcher{constructor(Fn){this.getter=Fn;this.depIds=newSet();//拥有has函数可以判断是否存在某个idthis.deps=[];this.newDeps=[];//记录新一次的依赖this.newDepIds=newSet();this.get();}/***Evaluatethegetter,andre-collectdependencies.*/get(){/************修改的地方*******************************/pushTarget(this);//保存包装了当前正在执行的函数的Watcher/*******************************************/letvalue;try{value=this.getter.call();}catch(e){throwe;}finally{/************修改的地方*******************************/popTarget();/*******************************************/this.cleanupDeps();}returnvalue;}...}

4、测试

回到开头的场景,再来执行一下:

import{observe}from"./reactive";importWatcherfrom"./watcher";constdata={text:"hello,world",inner:"内部",};observe(data);constupdateMyComponent=()=>{console.log("子组件收到:",data.inner);};constupdateParentComponent=()=>{newWatcher(updateMyComponent);console.log("父组件收到:",data.text);};newWatcher(updateParentComponent);data.text="hello,liang";

执行的时候将入栈。new Watcher(updateParentComponent);Watcher

Vue2响应式系统之嵌套怎么实现

进入函数,执行的时候将入栈。updateParentComponentnew Watcher(updateMyComponent);Watcher

Vue2响应式系统之嵌套怎么实现

执行函数,收集当前,执行完毕后出栈。updateMyComponentdata.innerDep.targetWatcher

Vue2响应式系统之嵌套怎么实现

继续执行函数,收集当前。updateParentComponentdata.textDep.target

此时依赖就变得正常了,会触发函数,从而输出如下:data.textupdateParentComponent

子组件收到: 内部
父组件收到: hello, world
子组件收到: 内部
父组件收到: hello, liang

 </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
本文:Vue2响应式系统之嵌套怎么实现的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:Vue2响应式系统之分支切换怎么实现下一篇:

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

(必须)

(必须,保密)

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