浅学一下 --- Vue 中的 nextTick

50 阅读3分钟

nextTick

首先:

在 Vue 中,数据更新和 DOM 更新是异步的过程。当修改 Vue 组件的数据时,Vue 会将这些变更加入到队列中,然后等待当前的 JavaScript 执行栈清空后再执行实际的 DOM 更新。这意味着,如果尝试在数据变更之后立即访问 DOM 元素,可能会获得之前的 DOM 状态,而不是最新的状态。

那么问题来了,我就是要呢~~~~

image.png

nextTick 是 Vue.js 中的一个方法,用于在 DOM 更新之后执行回调函数

  1. 操作 DOM 元素:在 Vue 组件更新后操作 DOM 元素时,nextTick 可以确保操作在 DOM 更新完成后执行,可以使用 nextTick 来操作已渲染的 DOM 元素
<template>
  <div ref="myElement">This is a div element.</div>
</template>

<script>
export default {
  mounted() {
    this.$nextTick(() => {
      // 操作DOM元素
      const element = this.$refs.myElement;
      element.style.backgroundColor = 'blue';
    });
  }
}
</script>
  1. 在更新数据后执行回调:更改了组件的数据,然后需要在数据更新后执行一些操作时。例如,可以监听某个数据的变化,并在 nextTick 中执行操作
<template>
  <div>
    <button @click="changeColor">Change Color</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      backgroundColor: 'red'
    };
  },
  methods: {
    changeColor() {
      this.backgroundColor = 'green';

      this.$nextTick(() => {
        // 在数据更新后执行操作
        console.log('Background color has changed to green.');
      });
    }
  }
}
</script>
  1. 动态添加子组件:在组件中动态添加子组件并等待其渲染完成后执行操作时,nextTick 可以派上用场。例如,可以在 v-ifv-for 中使用 nextTick
<template>
  <div>
    <button @click="addItem">Add Item</button>
    <div v-for="item in items" :key="item">
      {{ item }}
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      items: []
    };
  },
  methods: {
    addItem() {
      this.items.push('New Item');

      this.$nextTick(() => {
        // 子组件已渲染完成
        console.log('New Item is rendered.');
      });
    }
  }
}
</script>

为什么可以拿到最新的 dom 元素?🤔️

nextTick 的作用是在当前更新队列被清空后执行回调函数,确保在回调函数中能够访问到最新的 DOM 元素。这对于处理 Vue 组件中的数据更新后的操作非常有用,因为 Vue 默认将这些操作放在一个事件循环的微任务中,确保它们在 DOM 更新后执行。

为什么是微任务,不能是宏任务?🤔️

  1. 性能和效率:微任务通常比宏任务更高效,因为微任务在主线程执行期间会在事件循环的特定点触发,而不会延迟到下一个事件循环中。这意味着 nextTick 回调会尽可能快地执行,而不会导致额外的延迟。

  2. DOM 更新同步性nextTick 的主要用途是在 DOM 更新之后执行回调,以确保操作不会干扰到正在进行的更新。如果 nextTick 是宏任务,那么回调可能会在下一个事件循环中执行,这样就无法确保回调在 DOM 更新之后执行。

为什么要模拟微任务和宏任务?🤔️

nextTick 的核心思想是利用 JavaScript 中的一些原生方法,如 Promise、MutationObserver、setImmediate、setTimeout 等,来模拟微任务和宏任务的执行过程。这些方法允许开发者安排代码在未来某个时间点执行,从而实现异步操作。Vue 利用这些方法来建立自己的异步任务队列,以处理 Vue 内部的 DOM 更新和其他异步操作。

引入异步更新队列机制的原因∶

  • 如果是同步更新,则多次对一个或多个属性赋值,会频繁触发 UI/DOM 的渲染,可以减少一些无用渲染
  • 同时由于 VirtualDOM 的引入,每一次状态发生变化后,状态变化的信号会发送给组件,组件内部使用 VirtualDOM 进行计算得出需要更新的具体的 DOM 节点,然后对 DOM 进行更新操作,每次更新状态后的渲染过程需要更多的计算,而这种无用功也将浪费更多的性能。