• $nextTick和setTimeout区别(宏任务微任务)


    nextTick 在vue 源码中是利用 Promise.resolve()实现的。该问题实际就是Promise与setTimeout的区别,本质是Event Loop中微任务与宏任务的区别。

    nextTick:在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。

    简单点说就是 DOM更新后会执行的一个回调方法
    setTimeout:只是延迟执行,在延迟执行的方法里,DOM有可能会更新也有可能没有更新。
    常规做法就是延迟500ms或者1s

    $nextTick:一般使用在DOM操作上的,Vue在更新data之后并不会立即更新DOM上的数据,就是说**如果我们修改了data中的数据,再马上获取DOM上的值,我们取得的是旧值**。官网的原话是在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。我们把获取DOM上值的操作放进$nextTick里,就可以得到更新后得数据。

    setTimeout:就是个延时回调,和DOM操作无关。

    建议使用nextTick在有涉及DOM更新的场景

    JS中的Event Loop
    我们都明白,javascript是单线程的,所有的任务都会在主线程中执行的,当主线程中的任务都执行完成之后,系统会 “依次” 读取任务队列里面的事件,因此对应的异步任务进入主线程,开始执行。

    但是异步任务队列又分为: macrotasks(宏任务) 和 microtasks(微任务)。 他们两者分别有如下API:

    macrotasks(宏任务): setTimeout、setInterval、setImmediate、I/O、UI rendering 等。
    microtasks(微任务): Promise、process.nextTick、MutationObserver 等。
    promise的then方法的函数会被推入到 microtasks(微任务) 队列中(Promise本身代码是同步执行的),而setTimeout函数会被推入到 macrotasks(宏任务) 任务队列中,在每一次事件循环中 macrotasks(宏任务) 只会提取一个执行,而 microtasks(微任务) 会一直提取,直到 microtasks(微任务)队列为空为止。

    也就是说,如果某个 microtasks(微任务) 被推入到执行中,那么当主线程任务执行完成后,会循环调用该队列任务中的下一个任务来执行,直到该任务队列到最后一个任务为止。而事件循环每次只会入栈一个 macrotasks(宏任务), 主线程执行完成该任务后又会循环检查 microtasks(微任务) 队列是否还有未执行的,直到所有的执行完成后,再执行 macrotasks(宏任务)。 依次循环,直到所有的异步任务完成为止。

    现在我们来看一个简单的例子分析一下:

    1.     console.log(1);
    2.     setTimeout(function(){
    3.       console.log(2);
    4.     }, 0);
    5.     new Promise(function(resolve) {
    6.       console.log(3);
    7.       for (var i = 0; i < 100; i++) {
    8.         i === 99 && resolve();
    9.       }
    10.       console.log(4);
    11.     }).then(function() {
    12.       console.log(5);
    13.     });
    14.     console.log(6);
    15. 打印结果:
    16. 再试试这个复杂点的例子:
    17.   console.log(1);
    18.   setTimeout(function(){
    19.     console.log(2);
    20.   }, 10);
    21.   new Promise(function(resolve) {
    22.     console.log(3);
    23.     for (var i = 0; i < 10000; i++) {
    24.       i === 9999 && resolve();
    25.     }
    26.     console.log(4);
    27.   }).then(function() {
    28.     console.log(5);
    29.   });
    30.   setTimeout(function(){
    31.     console.log(7);
    32.   },1);
    33.   new Promise(function(resolve) {
    34.     console.log(8);
    35.     resolve();
    36.   }).then(function(){
    37.     console.log(9);
    38.   });
    39.   console.log(6);


      


    值得一提的是,微任务执行完成后,就执行第二个宏任务setTimeout,由于第一个setTimeout是10毫秒后执行,第二个setTimeout是1毫秒后执行,因此1毫秒的优先级大于10毫秒的优先级,因此最后分别打印 7, 2 了

    而很多人会发现vue中的nextTick会比setTimeout优先级高,就是因为nextTick是以微任务Promise.then优先的。

    Vue的特点之一就是能实现响应式,但数据更新时,DOM不会立即更新,而是放入一个异步队列中,因此如果在我们的业务场景中,有一段代码里面的逻辑需要在DOM更新之后才能顺利执行,这个时候我们可以使用this.$nextTick() 函数来实现。
     

  • 相关阅读:
    leetcode 70.爬楼梯、322.零钱兑换、279.完全平方数
    数据结构与算法-第八章 选择排序
    一文搞懂序列化
    熟悉Redis命令行
    11.盛最多水的容器 C++
    【YOLO系列】YOLOv4
    初步了解nodejs语法和web模块
    Connor学Android - JNI和NDK编程
    深度学习自学笔记十四:图像分割的简单网络介绍
    C++ 设计模式 —— 组合模式
  • 原文地址:https://blog.csdn.net/qq_41328247/article/details/132755678