如何在Vue中使用 nextTick()

105 阅读1分钟

如何在Vue中使用 nextTick()

Vue组件的数据(道具或状态)的变化不会立即反映在DOM中。相反,Vue会异步更新DOM。

你可以使用Vue.nextTick()vm.$nextTick() 函数来捕捉Vue更新DOM的时刻。让我们详细看看这些函数是如何工作的。

1.Vue.nextTick()

当改变Vue组件数据时,DOM会异步更新。Vue从所有的组件中收集对虚拟DOM的多次更新,然后尝试创建一个单一的批次来更新DOM。

例如,让我们考虑一个切换元素显示的组件。

<template>
  <div>
    <button @click="handleClick">Insert/Remove</button>
    <div v-if="show" ref="content">I am an element</div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      show: true,
    };
  },
  methods: {
    handleClick() {
      this.show = !this.show;
      console.log(this.show, this.$refs.content);
    },
  },
};
</script>

点击插入/移除按钮会改变this.show 的数据,它使用v-if="show" 指令来切换<div id="content"> 元素的显示。

handleClick 处理程序中,记录到控制台的this.show 值与记录到控制台的引用不一致。例如,如果this.showtrue ,那么this.$refs.contentundefined :这意味着DOM与组件的数据不同步。

如果你想抓住DOM刚刚被更新的时刻,那么你需要使用一个特殊的函数Vue.nextTick(callback) 。它在新的数据更新到达DOM后立即执行callback

让我们找到<div> 元素被插入或从DOM中移除的时刻。

<template>
  <div>
    <button @click="handleClick">Insert/Remove</button>
    <div v-if="show" ref="content">I am an element</div>
  </div>
</template>
<script>
import Vue from "vue";
export default {
  data() {
    return {
      show: true,
    };
  },
  methods: {
    handleClick() {
      this.show = !this.show;
      Vue.nextTick(() => {
        console.log(this.show, this.$refs.content);
      });
    },
  },
};
</script>

打开演示,点击几次插入/移除按钮。你会看到this.$refs.content (包含<div> 元素的引用)是undefined ,或者包含一个元素--与this.show 的值完全对应。

同时,Vue.nextTick(callback) ,当所有的子组件更新都提交给DOM时,就会执行callback

2. this.$nextTick()

Vue允许在组件实例上使用this.$nextTick(callback)

在下面的例子中,handleClick() 方法改变了this.show 的数据,并且立即设置了this.$nextTick() 来捕捉这个更新到达DOM的时刻。

<template>
  <div>
    <button @click="handleClick">Insert/Remove</button>
    <div v-if="show" ref="content">I am an element</div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      show: true,
    };
  },
  methods: {
    handleClick() {
      this.show = !this.show;
      this.$nextTick(() => {
        console.log(this.show, this.$refs.content);
      });
    },
  },
};
</script>

this.$nextTick() 如果你想访问当前组件实例的更新,使用NextTick()更方便。

3. nextTick() with async/await

如果Vue.nextTick()this.$nextTick() 被调用而没有参数,那么这些函数就会返回一个承诺,当组件数据变化到达DOM时就会被解决。

这有助于利用更可读的async/await 语法。

例如,让我们通过用async/await 语法来捕捉DOM的更新,使前面的组件更具可读性。

<template>
  <div>
    <button @click="handleClick">Insert/Remove</button>
    <div v-if="show" ref="content">I am an element</div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      show: true,
    };
  },
  methods: {
    async handleClick() {
      this.show = !this.show;
      await this.$nextTick();
      console.log(this.show, this.$refs.content);
    },
  },
};
</script>

async handleClick() 已经被标记为一个异步函数。

插入/移除按钮被点击时,this.show 的值会发生变化。

await this.$nextTick() 等待,直到这些变化到达DOM。最后, console.log(this.$refs.content)记录引用的实际内容。

我的建议是使用this.$nextTick()async/await 语法,因为它比回调的方法更容易阅读。

4.总结

当你改变组件的数据时,Vue会异步地更新DOM。

如果你想在组件数据改变后捕捉到DOM被更新的时刻,那么你需要使用Vue.nextTick(callback)this.$nextTick(callback) 函数。

它们的单个callback 参数将在DOM更新后立即被调用:并且你可以保证获得与组件数据同步的最新DOM。

另外,如果你不提供回调参数给Vue.nextTick()this.$nextTick(): 那么这些函数将返回一个正在解决DOM更新时的承诺。

使用这样的async/await 语法使代码比回调的方法更易读。

喜欢这篇文章吗?请分享!