简单了解Vue中 nextTick的原理和源码与使用

82 阅读2分钟

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是'井柏然'的打印 123.png

当点击完按钮时,打印如下: image.png 下面简单分析一下每个输出: image.png nextTick1注意它虽然放在$nextTick的回调中,在下一个tick执行,但是他的位置是在this.name='jingboran'的前面,也就是说,他的cb会比App的派发更新更先进入队列,当nextTick打印时,App组件还未派发更新,所以拿到的还是旧的DOM值。

nextTick其实在Vue中也算是比较核心的一个东西,因为贯穿整个Vue应用的组件化、响应式的派发更新与其息息相关。

nextTick原理

vue环境支持微任务的话,就使用微任务,否则就使用宏任务。 在代码里,微任务有:

  1. Promise
  2. MutationOBserver

宏任务有:

  1. MessageChannel(2.6版本下使用)
  2. setlmmediate(IE11)
  3. 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。