nextTick是什么?
1. 首先我们要去了解nextTick是Vue提供的一个全局API,也可以理解为全局API之一,由于Vue的异步更新策略导致我们对数据的修改不会立刻体现出来,在DOM变化上,此时如果想要立即获取更新后的DOM状态,就需要使用这个方法。
2. Vue在更新DOM时是异步执行的。只要监听到数据变化,Vue将开启一个队列,并且缓冲在同一事件循环中发生的所有数据变更,nextTick方法会在队列中加入一个🔍回调)函数,确保该函数在前面的DOM操作完成后才调用
3. 在下次DOM更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法获取更新后的DOM。所以放在Vue.nextTick()回调函数中。
4.nextTick主要使用了宏任务和微任务
5. 总结:简单理解就是当数据更新了,在DOM中渲染后,自动执行该函数
nextTick的使用
- 全局中:Vue.nextTick
- 组件中:this.$nextTick
<template>
<div>
<p ref="name">{{name}}</p>
<button @click="handleClick">修改name</button>
</div>
</template>
<script>
export default {
name:'App',
data() {
return {
name:'井柏然'
}
},
mounted() {
console.log('mounted',this.$refs.name.innerText);
},
methods: {
handleClick(){
this.$nextTick(()=>console.log('nextTick1',this.$refs.name.innerText))
this.name='jingboran'
console.log('sync log',this.$refs.name.innerText);
this.$nextTick(() => console.log('nextTick2',this.$refs.name.innerText))
}
},
}
</script>
如图所示mounted时候的innerText是'井柏然'的打印
当点击完按钮时,打印如下:
下面简单分析一下每个输出:
nextTick1注意它虽然放在$nextTick的回调中,在下一个tick执行,但是他的位置是在this.name='jingboran'的前面,也就是说,他的cb会比App的派发更新更先进入队列,当nextTick打印时,App组件还未派发更新,所以拿到的还是旧的DOM值。
nextTick其实在Vue中也算是比较核心的一个东西,因为贯穿整个Vue应用的组件化、响应式的派发更新与其息息相关。
nextTick原理
vue环境支持微任务的话,就使用微任务,否则就使用宏任务。 在代码里,微任务有:
- Promise
- MutationOBserver
宏任务有:
- MessageChannel(2.6版本下使用)
- setlmmediate(IE11)
- 3.setTimeout
那么宏任务为什么不直接使用setTimeout这一种宏任务呢,原因就是setTimeout太慢了,HTML5中规定setTimeout的最小时间延迟是4ms,为了让 回调函数尽早调用, setImmediate, 这几个函数明显比setTimeout快
所以 Vue.nextTick 有时候是微任务有时候是宏任务。
1、Vue 一般情况下使用的是微任务,因为新版本浏览都实现了Promise,只有但Chrome27,FireFox32,IE11及以下的浏览器不支持,它只能使用宏任务。
2、在绑定DOM 事件的时候,会使用宏任务, isUsingMicroTask标志就是起这个作用 。
在 Vue 2.4 之前都是使用的 microtasks(微任务),但是 microtasks 的优先级过高,在某些情况下可能会出现比事件冒泡更快的情况,但如果都使用 macrotasks(宏任务) 有可能会出现渲染的性能问题。所以在新版本中,会默认使用 microtasks,但在特殊情况下会使用 macrotasks。比如 v-on。