nextTick 的使用及其实现原理(Vue3)

文章讲述了Vue中的nextTick函数如何在状态改变后延迟DOM更新,确保性能优化,以及其工作原理和使用示例。它利用Promise的微任务机制,确保回调在所有组件更新完成后再执行,保证了DOM的正确渲染。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

nextTick 的使用

官方链接:https://cn.vuejs.org/api/general.html#nexttick

  • 当你在 Vue 中更改响应式状态时,最终的 DOM 更新并不是同步生效的,而是由 Vue 将它们缓存在一个队列中,直到下一个“tick”才一起执行。这样是 为了确保在一定时间内,每个组件无论发生多少状态改变,都仅执行一次更新

  • nextTick() 可以在状态改变后立即使用,以等待 DOM 更新完成。你可以传递一个回调函数作为参数,或者 await 返回的 Promise。

个人注解:vue 这样实现的目的是为了性能优化,避免不必要的资源浪费,只需要确保组件可以被正确渲染,程序可以正常运行即可,在这个基础上可以进行一定程度的性能优化。

  • 示例
import { ref, nextTick } from 'vue'

const count = ref(0)

async function increment() {
  count.value++

  // DOM 还未更新
  console.log(document.getElementById('counter').textContent) // 0

  // 方式1:
  await nextTick()
  // DOM 此时已经更新
  console.log(document.getElementById('counter').textContent) // 1
  
  // 方式2:将更新DOM后才执行的逻辑放到nextTick的参数函数中,该回调函数会在DOM更新完成后,自动执行
  nextTick(() => {
  	// DOM 此时已经更新
    console.log(document.getElementById('counter').textContent) // 1
  })
}
<button id="counter" @click="increment">{{ count }}</button>

Vue3 中的 nextTick 源码

官方链接:https://cn.vuejs.org/api/general.html#nexttick

  • 当你在 Vue 中更改响应式状态时,最终的 DOM 更新并不是同步生效的,而是由 Vue 将它们缓存在一个队列中,直到下一个“tick”才一起执行。这样是 为了确保在一定时间内,每个组件无论发生多少状态改变,都仅执行一次更新

  • nextTick() 可以在状态改变后立即使用,以等待 DOM 更新完成。你可以传递一个回调函数作为参数,或者 await 返回的 Promise。

github 源码地址:https://github.com/vuejs/core/blob/main/packages/runtime-core/src/scheduler.ts

// scheduler.ts

export function nextTick<T = void>(
  this: T,
  fn?: (this: T) => void
): Promise<void> {
  // p 可以简单理解为是执行任务队列中的更新任务的 Promise
  const p = currentFlushPromise || resolvedPromise
  
  // fn 是传入 nextTick 的回调函数
  return fn ? p.then(this ? fn.bind(this) : fn) : p
}

知识补给:Promise.then 传入的回调函数是作为一个微任务去执行的,而微任务是在 DOM 结构更新之后,DOM 被渲染到页面上之前被调用的。

理解 nexTick 实现原理的核心:nextTick 就是将传入的回调函数作为 p.then 的实参,p.then 传入的实参函数是在 Promise 对象 p 执行完成(fulfilled)时,也就是在当前更新任务队列中的更新任务全部执行完成之后才被调用,被调用时, DOM 操作已经完成,DOM 结构已更新,只是 DOM 还没有被渲染到页面中,但是已经可以通过 js 获取到修改后的 DOM。

使用 nextTick

nextTick(() => {
  // DOM 此时已经更新
  // do someThing
  // ...
})
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

coderyzj

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值