Vue2响应式系统之异步队列怎么实现(vue,开发技术)

时间:2024-05-09 20:28:43 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

试想一下如果这里的 console.log 是渲染页面,那改变一次值就刷新一下页面,会造成严重的性能问题,页面也会不停的改变。

场景

import{observe}from"./reactive";importWatcherfrom"./watcher";constdata={a:1,b:2,c:3,};observe(data);constupdateComponent=()=>{console.log(data.a+data.b);};newWatcher(updateComponent);constupdateComponent2=()=>{console.log(data.c);};newWatcher(updateComponent2);data.a=2;data.a=3;data.b=4;data.c=5;

new Watcher(updateComponent) 进行依赖收集会输出一次 3 ,new Watcher(updateComponent2) 进行依赖收集也会输出一次 3 。

之后我们依次改变 a、 a 、b、c 的值,每改变一次就会触发 Watcher 的执行,会连续进行四次的 console.log。

Vue2响应式系统之异步队列怎么实现

试想一下如果这里的 console.log 是渲染页面,那改变一次值就刷新一下页面,会造成严重的性能问题,页面也会不停的改变。

解决方案

我们可以通过一个队列,收集所有的 Watcher 。

那什么时候执行 Watcher 队列呢?

为了等所有的 Watcher 都收集完毕,可以将 Watcher 的执行放到 setTimeout 中。这样当主线程全部执行后,才会去执行 Watcher 队列。

代码实现

我们可以给每一个 Watcher 加上一个 id,如果队列中已经有 id 了就不加入队列。

letuid=0;exportdefaultclassWatcher{constructor(Fn,options){this.getter=Fn;this.depIds=newSet();//拥有has函数可以判断是否存在某个idthis.deps=[];this.newDeps=[];//记录新一次的依赖this.newDepIds=newSet();/******新增*************************/this.id=++uid;//uidforbatching//optionsif(options){this.sync=!!options.sync;}/************************************/this.get();}...}

我们同时提供了一个 options 对象,保存了其中的 sync 字段,表示是像之前一样立即出触发 Watcher 还是放到队列中。

然后 Watcher 的 update 方法中我们去调用加入队列的函数。

exportdefaultclassWatcher{...update(){if(this.sync){this.run();//直接运行}else{queueWatcher(this);//加入队列}}...}

看一下 queueWatcher 的实现。

constqueue=[];//保存Watcher队列lethas={};//去重Watcherletwaiting=false;//是否加入到了setTimeout队列exportfunctionqueueWatcher(watcher){constid=watcher.id;if(has[id]==null){has[id]=true;queue.push(watcher);//加入队列//queuetheflushif(!waiting){//执行Watcher函数放到setTimeout队列中,只加入一次即可waiting=true;setTimeout(flushSchedulerQueue,0);}}}

再看一下上边执行 Watcher 队列的 flushSchedulerQueue 函数的实现。

letflushing=false;//是否正在执行队列letindex=0;/***Flushbothqueuesandrunthewatchers.*/functionflushSchedulerQueue(){flushing=true;letwatcher,id;for(index=0;index<queue.length;index++){watcher=queue[index];id=watcher.id;has[id]=null;watcher.run();}resetSchedulerState();//执行结束后进行重置}/***Resetthescheduler'sstate.*/functionresetSchedulerState(){index=queue.length=0;has={};waiting=flushing=false;}

总体上就是上边的样子了。

执行结果

import{observe}from"./reactive";importWatcherfrom"./watcher";constdata={a:1,b:2,c:3,};observe(data);constupdateComponent=()=>{console.log(data.a+data.b);};newWatcher(updateComponent);constupdateComponent2=()=>{console.log(data.c);};newWatcher(updateComponent2);data.a=2;data.a=3;data.b=4;data.c=5;

虽然后边我们改变了四次 data 中的值,但事实上只有两个 Watcher ,因此只会输出两次。

Vue2响应式系统之异步队列怎么实现

 </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
本文:Vue2响应式系统之异步队列怎么实现的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:如何理解从数字化转型到数据架构下一篇:

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

(必须)

(必须,保密)

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