持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第22天,点击查看活动详情
说说$nextTick的原理?
$nextTick会在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM
一、原理
- 当数据的值发生变化,Vue并不会立刻更新DOM,而是将数据变化的 watcher 放入一个异步操作队列中
- 有去重操作,多次触发只会入队一次,避免非必要的DOM操作
- 等同一数据循环中的所有数据变化完成之后,再统一进行视图更新。
nextTick会在DOM渲染之后被触发,在修改数据之后立即调用 this.$nextTick(callback) ,就可以获取最新的DOM节点
源码部分的理解:
官方源码指路:github.com/vuejs/vue/b…
-
执行环境检测(降级处理):
首先会检测当前的执行环境是否支持Promise.then,MutationObserver(监听节点、DOM变化),setImmediate,setTimeout。
进行降级处理的目是将
flushCallbacks函数放入微任务或者宏任务。支持哪种方式就用哪种来触发执行回调函数,优先执行微任务(因为宏任务耗费的时间⼤于微任务)- 微任务: Promise.then、MutationObsever
- 宏任务: setTimeout、setImmediate;
注:如果前三个都不支持,最后选择setTimeout,执行setTimeout(flushCallbacks, 0)
-
执行回调队列中的每一个回调:
- 执行环境检测后,会得到⼀个延迟回调函数
timerFunc,随后开始执行nextTick函数 - 将回调函数放入回调队列,遍历执行回调函数
- 如果没有提供回调,并且支持Promise,会返回一个Promise
- 执行环境检测后,会得到⼀个延迟回调函数
二、使用方法
this.value = '已修改'
// 此时DOM未更新,依旧是修改前的状态
this.$nextTick(() => {
// 此时DOM已更新,可以获取变化后的 DOM
})
或:
this.value = '已修改'
// 此时DOM未更新
await this.$nextTick()
// 此时DOM已更新,可以获取变化后的 DOM
注:全局 API 使用 Vue.nextTick()
三、应用场景
- 在数据变化后要立即执行某个操作时
- 在生命周期
created()中进行的DOM操作要放在Vue.nextTick()的回调函数中(因为此阶段DOM还未进行渲染)