Vue 源码之 nextTick

前言

为什么要写一篇关于 nextTick 的源码分析呢?

主要是因为 nextTick 与 JS 的事件循环(Event Loop)有关,这块知识还是比较重要的,尤其当我们的程序复杂了,很可能就会遇到因为 JS 顺序导致的问题。

本文基于 2.6.11 版本的代码进行分析。

事件循环

JS 执行是单线程的,它是基于事件循环的。事件循环大致分为以下几个步骤:

  1. 所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
  2. 主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
  3. 一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
  4. 主线程不断重复上面的第三步。

其中异步任务又分为宏任务(macro task)和微任务(micro task),在浏览器环境:

  • 宏任务
    • script 标签中的代码
    • setTimeout
    • setInterval
    • setImmediate
    • MessageChannel
    • I/O
    • UI 交互事件
    • requestAnimationFrame
  • 微任务
    • Promise.then
    • MutationObsever

Node.js 和这个有些不同,这里不展开说明了,感兴趣可以参考这里

  1. 程序开始执行时,执行栈中没有任务。
  2. 微任务队列也没有任务,我们平时写的 script 中的代码算作宏任务,所以主线程就会从宏任务队列中取出一个任务放到执行栈中进行执行。
  3. 在执行栈中的代码执行完后,就会从微任务队列中取出所有任务放到执行栈中进行执行。

至此,一次事件循环就结束了,接下来继续循环上面的步骤。循环逻辑用代码表示如下:

for (macroTask of macroTaskQueue) {
   
    // 1. Handle current MACRO-TASK
    handleMacroTask();
      
    // 2. Handle all MICRO-TASK
    for (microTask of microTaskQueue) {
   
        handleMicroTask(microTask);
    }
}

nextTick 语法

我们先来看下 nextTick 的语法与介绍。

vm.$nextTick( [callback] )

将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。它跟全局方法 Vue.nextTick 一样,不同的是回调的 this 自动绑定到调用它的实例上。

这里注意,Vue 实例构造函数上都有 nextTick 方法。

什么情况下,我们会用到 nextTick 方法呢?

理想情况,我们改变了 Vue 中的数据状态,对应的 DOM 视图应该刷新。但是,Vue 中并没有这样做,它把 watch 的更新放到了队列当中,对应的代码细节可以查看 Vue 源码之 computed 和 watch 这篇博文。

export default class Watcher {
   
  update () {
   
    if (this.lazy) {
   
      this<
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值