如何在 Vue 中使用 nextTick()

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在 Vue 中使用 nextTick()相关的知识,希望对你有一定的参考价值。

参考技术A

vue 中组件的(props 或 state)发生变化时不会立刻在 DOM 中响应,Vue 是异步更新 DOM的。所以有时当你修改了组件状态后,立刻获取对应dom对象,会发现获取不到。这个时候,就要用到Vue.nextTick()。

让我们详细的看看nextTick()函数是如何工作的。

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

例如,让我们看下一个切换元素显示的组件:

单击 显示/隐藏 按钮更改 this.show 值,然后使用指令 v-if="show" 切换 元素的显示。

在 handleClick 函数中 ,分别在控制台打印了this.show 和 this.$refs.content (包含该 元素的引用) 的元素对象 ,此时会发现他们的结果不一致。 当 this.show 值为 true 时 , 结果 this.$refs.content is 值却是 undefined ,这意味着 DOM 与组件的数据不同步。

如果你想捕捉 DOM 刚刚更新的那一刻,那么你需要使用一个特殊的函数 Vue.nextTick(callback) 。

在DOM响应数据的变化后,会立刻执行 callback 回调函数。

这时,点击 显示/隐藏 按钮更改 this.show 值时,您会看到 this.$refs.content 与 this.show 值完全对应。

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

在下面的示例 handleClick() 方法中更改 this.show 值,并使用 this.$nextTick() 捕捉DOM的更新:

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

如果在没有参数的情况下调用 Vue.nextTick() 或 this.$nextTick() ,则函数返回一个 promise。

使用 async/await 语法更具可读性的。

例如,让我们通过使用以下 async/await 语法捕获 DOM 更新:

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

点击 显示/隐藏 按钮时, this.show 值会发生变化。

await this.$nextTick() 等待DOM的更改,在控制台打印 console.log(this.$refs.content) 引用的元素对象。

建议使用 async/await 语法,因为它比回调方法更具可读性。

在 vuejs 中使用 vue $nextTick 与 setTimeout 0 有啥区别

【中文标题】在 vuejs 中使用 vue $nextTick 与 setTimeout 0 有啥区别【英文标题】:What is the difference between using vue $nextTick vs setTimeout 0 in vuejs在 vuejs 中使用 vue $nextTick 与 setTimeout 0 有什么区别 【发布时间】:2020-12-19 12:18:21 【问题描述】:

从Vue.js documentation,$nextTick 解释为:

将回调推迟到下一个 DOM 更新周期后执行。更改一些数据后立即使用它以等待 DOM 更新。

太棒了!所以第二条语句说在某些数据发生变化后立即使用它,我知道 setTimeout 与 0 也被立即调用。我创建了这个little sandbox 来理解这两种方法,但我似乎仍然没有理解这两种方法之间的区别?

我们将不胜感激任何关于它们差异的解释。

【问题讨论】:

【参考方案1】:

不同之处在于$nextTick 知道DOM 何时更新并相应地触发,而setTimeout 是幂等的并在 指定的毫秒延迟后触发。后者见this excellent answer,但要点是延迟是最小的,而不是确切的超时。


例如,您有一些状态会触发包含 <input> 元素

<input ref="textBox" v-if="showTextBox">

使用$nextTick,您可以安全地执行以下操作,因为只有在 DOM 更新为包含 &lt;input&gt; 后才会执行回调

this.showTextBox = true
this.$nextTick(() => 
  this.$refs.textBox.focus()
)

现在考虑(理论)情况,将&lt;input&gt; 添加到 DOM 所需的时间比触发 setTimeout 回调所需的时间长

this.showTextBox = true
setTimeout(() => 
  // will throw "Uncaught TypeError: Cannot read property 'focus' of undefined"
  this.$refs.textBox.focus() 
, 0)

【讨论】:

那么说 $nextTick 劫持数据并在不知道旧数据的情况下呈现它是否正确? 并非如此。它不会劫持任何东西。这只是表示 DOM 发生了变化的触发器或信号

以上是关于如何在 Vue 中使用 nextTick()的主要内容,如果未能解决你的问题,请参考以下文章

在 vuejs 中使用 vue $nextTick 与 setTimeout 0 有啥区别

vue中$nextTick的用法

vue中的$nextTick()

Vue中nextTick的正确使用

Vue系列---理解Vue.nextTick使用及源码分析

vue.nextTick()方法的使用详解