vue中的nextTick()

2023-10-14 09:03:59 浏览数 (1)

nextTick() 方法

nextTick() 方法是一个非常强大的工具,是一个等待下一次 DOM 更新刷新的工具方法。用于将一个函数以异步的方式推迟到下一个 DOM 更新周期执行。

当我们在 Vue 中更改响应式状态时,最终的 DOM 更新并不是同步生效的,而是由 Vue 将它们缓存在一个队列中,直到下一个“tick”才一起执行。这样是为了确保每个组件无论发生多少状态改变,都仅执行一次更新。

nextTick() 可以在状态改变后立即使用,它接受一个回调函数作为参数,该回调函数会在 DOM 更新周期结束时执行。nextTick() 方法可以将异步操作推迟到下一个 DOM 更新周期中执行,从而确保了在数据改变之后正确地获取到更新后的 DOM。

在vue中,nextTick()是一个Promise对象,因此我们也可以使用 await 返回的 Promise。

用法

回调函数方式使用

在 Vue 中,我们可以通过 nextTick() 方法来实现 nextTick() 方法的调用。nextTick() 方法是 Vue 提供的一个实例方法,可以用于在组件中执行异步操作。下面是一个使用 nextTick() 方法的简单示例:

代码语言:javascript复制
export default {
  data() {
    return {
      name: "Vue"
    };
  },
  methods: {
    showName() {
      console.log(this.$el.innerHTML);   // 'Vue'
    },
    updateName() {
      this.name = "Vue 4";
      this.$nextTick(this.showName);
    }
  }
}

在上面代码中,我们定义了一个组件,并在其中定义了一个 data 属性 name ,以及两个方法 showName 和 updateName 。showName 方法用于打印组件的 innerHTML ,updateName 方法用于修改 name 属性的值,并在修改完成后通过 $nextTick() 方法调用 showName 方法。这样做的目的是为了确保修改完成后再获取更新后的 DOM。 注意:我这里是使用的Vue2的写法, 采用的是Options API,通过在main.js中绑定this来使用的,如果是使用的Composition API,则这里的方法不适用。

await方式使用

代码语言:javascript复制
export default {
  data() {
    return {
      name: "Vue "
    };
  },
  methods: {
    showName() {
      console.log(this.$el.innerHTML);   // 'Vue '
    },
   async updateName() {
      this.name = "Vue 4";
      await this.$nextTick(); 
      this.showName(); 
    }
  }
}

实现原理

在Vue中,当我们对组件状态进行更改时,实际上是将其添加到一个更新队列中,在下次“更新周期”时将该队列中的所有更改应用于DOM。这种行为称为异步更新。

nextTick()方法在组件状态更改后提供了一个很好的时机来访问更新后的DOM。

Vue中的nextTick()方法是通过将回调包装在Promise和微任务队列之间来实现的。微任务是一个在当前任务完成后立即执行的任务,而Promise的then()是执行异步操作而不阻止主线程的一种方式。 Promise的resolve()方法是一个产生成功状态的Promise,可以用它来包装一个微任务队列,在队列的末尾添加一个新的任务。

nextTick()方法实现原理的示例代码如下:

代码语言:javascript复制
let callbacks = [] // 存储回调函数的数组
let pending = false // 标记是否有待处理的任务

// 执行任务队列的函数
const flushCallbacks = () => {
  // 标记为 "待处理任务" 的任务已处理
  pending = false 
  
  // 复制回调函数数组并清空当前数组,以防回调函数在执行期间被添加
  const copies = callbacks.slice(0)
  callbacks = []
  
  // 依次执行每个回调函数
  for (let i = 0; i < copies.length; i  ) {
    copies[i]()
  }
}

// 添加任务到任务队列的函数
const nextTick = (cb) => {
  callbacks.push(cb) // 将回调函数添加到待处理任务的数组中
  if (!pending) { // 如果当前没有待处理任务,则标记为待处理
    pending = true
    Promise.resolve().then(flushCallbacks) // 创建 Promise,并加入到微任务队列中,then()中执行 flushCallbacks() 函数
  }
}

使用时,我们直接调用nextTick()方法

代码语言:javascript复制
nextTick(() => {
    // 在DOM更新后执行回调函数
    console.log('DOM updated!')
})

在更新队列中添加的更改将在下一个“更新周期”中处理,在此期间,Vue将更改应用于DOM,因此在执行nextTick()回调时,可以看到最新的DOM状态。将回调加入队列,而不是将其立即添加到微任务队列中,可以避免在相同的常见情况下重复调用回调,从而提高性能。

使用nextTick() 方法时的注意事项

在使用 nextTick() 方法时,需要注意以下几点:

  • 不要过度依赖 nextTick() 方法,因为它会降低代码的可读性和可维护性。
  • nextTick() 方法是在下一个 DOM 更新周期结束时执行回调函数,因此回调函数可能会有一定的延迟。
  • 在使用 nextTick() 方法时,需要确保回调函数不会对 DOM 进行多次修改,从而避免影响性能。
  • 避免出现回调地狱:如果回调函数嵌套层数过多,可能会导致代码无法维护。
  • 适当地使用 nextTick() 方法:只有在需要在 DOM 更新后执行回调函数时才使用 nextTick() 方法。

nextTick() 方法是一个非常强大的方法,我们在开发过程中会经常用到它,但是在使用时应注意上面的几点,避免滥用,造成性能下降。

好了,关于nextTick() 方法的使用就聊到这里,喜欢的小伙伴点赞关注加收藏哦!

0 人点赞