nextTick的原理和使用场景

150 阅读1分钟

一、nextTick是什么?

在下次DOM更新循环结束之后,执行延迟回调

Vue在更新DOM时是异步执行的,当数据发生变化,vue不会立刻去更新don,而是去开启一个异步更新队列,视图需要等队列中所有数据变化完成之后,再统一进行更新。

为什么要有nextTick?

如果没有nextTick更新机制,那么每次数据变化都会触发视图更新,(比如频繁更新10万次),有了nextTick机制,只需要更新一次,所以nextTick本质是一种优化策略

二、使用场景

想要在数据修改后(想要在什么时候)立刻得到更新后的DOM,就可以使用Vue.nextTick() 第一个参数:回调函数(可以获取到最近DOM结构) 第二个参数:执行上下文

vm.message = '修改后的值'
//此时DOM还没更新
console.log(vm.$el.textContent) //原来的值
Vue.nextTick(function() {
    //DOM更新了
    console.log(vm.$el.textContent) //修改后的值
})

组件内通过this.$nextTick(),并且回调函数中的this自动绑定到当前的Vue实例上

this.message = '修改后的值'
console.log(this.$el.textContent) // => '原始的值'
this.$nextTick(function () {
    console.log(this.$el.textContent) // => '修改后的值'
})

$nextTick()会返回一个Promise对象,可以用async/await代替

三、实现原理

总结:

1、把回调函数放到callbacks等待执行

2、将执行函数放到微任务或宏任务中

3、事件循环到了微任务或者宏任务,一次执行callbacks中的回调

如果支持 Promise 就用 Promise
如果不支持就用 MutationObserver MDN-MutationObserver
MutationObserver 它会在指定的DOM发生变化时被调用
如果不支持 MutationObserver 的话就用 setImmediate MDN-setImmediate
但是这个特性只有最新版IE和node支持,然后是最后一个条件 如果这些都不支持的话就用setTimeout

顺序就是:promise -> MutationPbserver -> setImmediate -> setTimeout

跟Event Loop有关(单进程、同步异步、微任务宏任务)