资讯专栏INFORMATION COLUMN

【Vue原理】NextTick - 源码版 之 宏微任务的抉择

raise_yang / 1010人阅读

摘要:这么讲,有点笼统,准确地说,应该是事件回调执行过程中,在主线程为空之后,异步代码执行之前,所有通过注册的异步代码都是用宏任务。

写文章不容易,点个赞呗兄弟
专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧
研究基于 Vue版本 【2.5.17】

如果你觉得排版难看,请点击 下面链接 或者 拉到 下面关注公众号也可以吧

【Vue原理】NextTick - 源码版 之 宏微任务的抉择

nextTick 已经写了三篇文章啦,这是最后一篇源码版,没看过的童鞋可以看看白话版简单了解下拉

【Vue原理】NextTick - 白话版 简单了解下NextTick

在前面的文章 NextTick-源码版之独立自身 中

埋下过两个问题

1、Vue 在哪里使用到了 宏任务和 微任务

2、Vue 为什么需要 宏任务 和微任务

今天的任务就是解决这两个问题!!!

在这里,大家肯定必须一定要了解了 宏任务和 微任务的哈,这两个东西不赘述了

首先,第一个问题就是宏微任务的使用场景场景

宏微任务的使用场景

1、Vue 一般情况下使用的是微任务

2、在绑定DOM 事件的时候,会使用宏任务。

这么讲,有点笼统,准确地说,应该是

事件回调执行过程中,在JS 主线程为空之后,异步代码执行之前,所有通过 nextTick 注册的异步代码都是用宏任务。

来看看绑定DOM 事件的源码

通过 addEventListener 给 DOM 绑定事件

function add$1(event, handler) {
    handler = withMacroTask(handler);
    target$1.addEventListener(event, handler);

}



function withMacroTask(fn) {    

    return fn._withTask || (fn._withTask = function() {

        useMacroTask = true;        

        var res = fn.apply(null, arguments);

        useMacroTask = false;        

        return res

    })
}

你看到了,把原先DOM 事件的回调包装了一遍,然后通过设置 useMacroTask 来控制注册宏任务

useMacroTask 没见过,在 nextTick 独立流程中已经讲过了的

在调用 nextTick 的时候,正是通过这个变量来控制,此次异步代码注册的任务类型

Vue.nextTick =function (cb, ctx) {


    callbacks.push(function() {
        cb && cb.call(ctx);

    });    



    if (!pending) {

        pending = true;        

        if (useMacroTask) {

            macroTimerFunc();
        } else {
            microTimerFunc();
        }
    }
}

好多,现在我们来解决第二个问题!

为什么需要宏微任务

为什么要特地在事件回调执行期间 使用宏任务啊,想了好好久啊,才脑抽想到去看了下 Vue 的注释

大概意思是这样

本来 Vue 是从来都使用微任务的,因为微任务的优先级比较高,执行比较快。但是同时也是因为这样导致了一个问题

什么问题?

在连续事件发生的期间,微任务就已经执行了

就是

事件回调执行完成之后,会马上执行微任务

那么连续多个事件回调同时执行,就会导致连续多次执行微任务

如果连续多个事件回调中,都有修改数据,如下

this.state = xxxxx

那么很明显,会导致页面频繁的更新,这显然不是我们想要的结果

那到底什么是连续的事件?

那就是冒泡!

我们来现场演示一下微任务下的冒泡事件

div1.onclick = function() {    

    console.log("div1");

    Promise.resolve().then(() = >{        

        console.log("promise1")

    })
}

div2.onclick = function() {    

    console.log("div2");    

    Promise.resolve().then(() = >{        

        console.log("promise2")

    })
}

div3.onclick = function() {    

    console.log("div3");    

    Promise.resolve().then(() = >{        

        console.log("promise3")

    })
}

看到了吗,promise 在一个事件回调结束之后马上就调用了

如果在 Vue 中的事件回调中修改了数据 this.state = xxxxx

然后数据一更改,就会注册微任务用于响应更新,然后事件结束之后,马上执行微任务

如果三个事件回调都有修改数据,那么就会注册三次,执行三次,就会更新三次

所以

尤大想到了一个方法,就是在事件回调执行时,注册的是宏任务

宏任务并不会在事件结束之后马上调用

只会在连续事件结束之后,才调用,这就是我们想要的

所以你才能看到 使用 useMacroTask 来控制注册的任务类型

现在我把上面的例子中的 promise 换成 setTimeout,重新点击一下

但是!!

在 【Vue 2.6】 中,我们已经看不到 useMacroTask 的身影了,为什么?

因为 Vue 又全部使用微任务了........ 天道轮回.....

(其实并不是全部是微任务,兼容写法最后是 setTimeout)

你问,那冒泡又怎么办?

好吧,尤大想到了另一个办法来解决冒泡的问题

就是判断当时的 事件 target,来判断是否执行事件回调

也就间接解决了这个问题,看看新的绑定事件的源码

function add$1(name, handler) {
    handler = function(e) {        

        if (

            e.target === e.currentTarget ||

            e.target.ownerDocument !== document

        ) {  

          return  handler.apply(this, arguments)

        }
    };
    target$1.addEventListener(name, handler);
}

通过判断 target 就解决了冒泡,但是这样就不能用冒泡了好像??

也不知道有没有什么坏处,如果有的话,后面尤大肯定会更新的

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/110258.html

相关文章

  • Vue原理NextTick - 源码 独立自身

    摘要:尽量把所有异步代码放在一个宏微任务中,减少消耗加快异步代码的执行。我们知道,如果一个异步代码就注册一个宏微任务的话,那么执行完全部异步代码肯定慢很多避免频繁地更新。中就算我们一次性修改多次数据,页面还是只会更新一次。 写文章不容易,点个赞呗兄弟专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于 Vue版本 【2.5...

    刘东 评论0 收藏0
  • Vue原理NextTick - 源码 服务Vue

    写文章不容易,点个赞呗兄弟专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于 Vue版本 【2.5.17】 如果你觉得排版难看,请点击 下面链接 或者 拉到 下面关注公众号也可以吧 【Vue原理】NextTick - 源码版 之 服务Vue 初次看的兄弟可以先看 【Vue原理】NextTick - 白话版 简单了解下...

    Acceml 评论0 收藏0
  • Vue原理NextTick - 白话

    摘要:通常会做很多判断来选择存在的类型,比如判断等是否存在,而选择他为微任务类型但是可能宏微任务最后都是,因为他是保守兼容处理。 写文章不容易,点个赞呗兄弟专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于 Vue版本 【2.5.17】 如果你觉得排版难看,请点击 下面链接 或者 拉到 下面关注公众号也可以吧 【V...

    zeyu 评论0 收藏0
  • Vue原理】Event - 源码 绑定标签DOM事件

    摘要:写文章不容易,点个赞呗兄弟专注源码分享,文章分为白话版和源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于版本如果你觉得排版难看,请点击下面链接或者拉到下面关注公众号也可以吧原理源码版之绑定标签事件这里的绑定 写文章不容易,点个赞呗兄弟专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于...

    phoenixsky 评论0 收藏0
  • 前方来报,八月最新资讯--关于vue2&3最佳文章推荐

    摘要:哪吒别人的看法都是狗屁,你是谁只有你自己说了才算,这是爹教我的道理。哪吒去他个鸟命我命由我,不由天是魔是仙,我自己决定哪吒白白搭上一条人命,你傻不傻敖丙不傻谁和你做朋友太乙真人人是否能够改变命运,我不晓得。我只晓得,不认命是哪吒的命。 showImg(https://segmentfault.com/img/bVbwiGL?w=900&h=378); 出处 查看github最新的Vue...

    izhuhaodev 评论0 收藏0

发表评论

0条评论

raise_yang

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<