什么是nextTick或在VueJs中做什么


104

我阅读了文档,但我听不懂。我知道哪些数据可以计算,监视,执行方法,但是nextTick()在vuejs中有什么用?


17
要理解的关键概念是DOM是异步更新的。当您在Vue中更改值时,更改不会立即呈现给DOM。而是,Vue将DOM更新排队,然后在计时器上更新DOM。通常,此过程发生得如此之快以至于没有任何区别,但是有时您需要在Vue渲染后更新渲染的DOM,由于无法进行更新,因此您不能立即在方法中执行此操作然而。在这种情况下,您可以使用nextTick记录在这里
Bert

补充上述@Bert在https://stackoverflow.com/q/47634258/9979046中所说的内容,例如,当您需要检查DOM(HTML)中是否存在元素时,将在单元测试中使用nextTick(),如果您收到有关Axios请求的信息。
奥斯卡·阿伦卡

Answers:


139

在更改数据之后,VueJS根据您的数据更改,但在浏览器将更改内容呈现在页面上之前,nextTick允许您执行某些操作。

通常,开发人员使用本机JavaScript函数setTimeout来实现类似的行为。但是,在setTimeout将控制权通过回调回调给您之前,先将控制权交给浏览器。

假设您更改了一些数据。Vue根据数据更新DOM。请注意,浏览器尚未将DOM更改呈现到屏幕上。如果使用nextTick,则立即调用您的回调。然后,浏览器更新页面。如果您使用setTimeout,则您的回调将仅在现在被调用。

您可以通过创建一个类似于以下内容的小组件来形象化此行为:

<template>
  <div class="hello">
    {{ msg }}
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data() {
    return {
        msg: 'One'
    }
  },
  mounted() {
      this.msg = 'Two';

      this.$nextTick(() => {
          this.msg = 'Three';
      });
  }
}
</script>

运行本地服务器。您将看到Three显示的消息。

现在,this.$nextTicksetTimeout

setTimeout(() => {
    this.msg = 'Three';
}, 0);

重新加载浏览器。您将看到Two,然后再看到Three

检查这个小提琴以观看它的现场直播

这是因为,Vue将DOM更新为Two,将控制权交给了浏览器。显示浏览器Two。然后,调用您的回调。Vue将DOM更新为Three。浏览器再次显示的内容。

有了nextTick。Vue将DOM扩展为Two。调用了您的回调。Vue将DOM更新为Three。然后将控制权交给浏览器。并且,浏览器显示Three

希望这很清楚。

要了解Vue如何实现这一点,您需要了解事件循环微任务的概念。

一旦清除了这些概念,请检查nextTick源代码


4
我不明白的一件事是,当您说“ vue更新数据”时,是指用ex进行的更新:this.name = 'foo'还是指页面中注入html元素?
hidar

在这个问题的历史记录中,我看不到他说“ Vue更新数据” ...他确实说“ Vue根据数据更新DOM”。这意味着当您通过this.name = 'foo'vue 设置数据时,将更新文档对象模型,以反映基于所配置的模板和功能对数据所做的更改。
ADJenks

24

内容已从采取通过阿德里亚Fontcuberta

Vue文档说:

Vue.nextTick([回调,上下文])

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

嗯...,如果刚开始觉得很吓人,请不要担心,我会尽力解释得尽可能简单。但是首先,您应该知道两件事:

  1. 它的用法并不常见。就像其中的一张银色魔术卡一样。我已经编写了几个Vue应用程序,并且一次或两次遇到了nextTick()。

  2. 一旦您看到了一些实际的用例,就更容易理解。有了这个主意,恐惧就会消失,并且您会得到一个方便的工具。

那我们去吧。

了解$ nextTick

我们是程序员,不是吗?我们将使用我们钟爱的分而治之的方法来尝试.nextTick()一点一点地翻译描述。它开始于:

推迟回调

好的,现在我们知道它接受了回调。所以看起来像这样:

Vue.nextTick(function () {
  // do something cool
});

大。此回调被延迟(这就是千禧一代所说的延迟),直到…

下一个DOM更新周期。

好的。我们知道Vue异步执行DOM更新。它具有一种将这些更新“存储”到需要应用它们的方式。它创建更新队列,并在需要时刷新它。然后,“修补” DOM,并将其更新为最新版本。

什么?

让我再试一次:假设您的组件确实完成了一些必不可少的事情,并且很聪明,例如this.potatoAmount = 3.Vue不会自动重新渲染该组件(以及DOM)。它将排队所需的修改。然后,在下一个“滴答声”中(如在时钟中),刷新队列,并应用更新。多田

好的!因此,我们知道可以nextTick()用来传递设置数据和DOM更新后立即执行的回调函数。

就像我之前说的那样。我不会提到的“数据流”方法可以驱动Vue,React和Google的另一种方法,这在大多数情况下都是不必要的。但是,有时我们需要等待某些元素在DOM中出现/消失/被修改。这是nextTick派上用场的时候。

更改一些数据以等待DOM更新后,请立即使用它。

究竟!这是Vue文档提供给我们的最后一个定义。在回调中,DOM已更新,因此我们可以与它的“最新”版本进行交互。

证明给我看

好吧好吧。查看控制台,您将看到仅在nextTick的回调内部更新了我们的数据值:

const example = Vue.component('example', {
  template: '<p>{{ message }}</p>',
  data: function () {
    return {
      message: 'not updated'
    }
  },
  mounted () {
    this.message = 'updated'

        console.log(
        'outside nextTick callback:', this.$el.textContent
    ) // => 'not updated'

    this.$nextTick(() => {
      console.log(
        'inside nextTick callback:', this.$el.textContent
      ) // => 'not updated'
    })
  }
})


new Vue({
  el: '#app',
    render: h => h(example)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.10/vue.js"></script>
<div id="app"></div>

用例

让我们尝试为定义一些有用的用例nextTick

想象一下,在安装组件时需要执行一些操作。但!不仅是组件。您还需要等待,直到其所有子级都已安装并在DOM中可用为止。该死的!我们安装的钩子不能保证整个组件树都能渲染。

如果我们只有一个工具可以等待下一个DOM更新周期…

哈哈

mounted() {
  this.$nextTick(() => {
    // The whole view is rendered, so I can safely access or query
    // the DOM. ¯\_(ツ)_/¯
  })
}

简而言之

因此:nextTick在设置数据和更新DOM之后,这是一种执行函数的简便方法。

您需要等待DOM,也许是因为您需要执行一些转换,还是需要等待外部库加载其内容?然后使用nextTick。

有些人还在其单元测试中使用nextTick,以确保数据已更新。这样,他们可以测试组件的“更新版本”。

Vue.nextTick()或vm。$ nextTick()吗?

不用担心 两者(几乎)相同。Vue.nextTick()引用全局API方法,而vm.$nextTick()引用是实例方法。唯一的区别是vm.$nextTick不接受上下文作为第二个参数。它总是绑定到this(也称为实例本身)。

最后一点凉意

请注意,它nextTick返回Promise,因此我们可以充分利用async/await并改进示例:

async mounted () {
    this.message = 'updated'
    console.log(this.$el.textContent) // 'not updated'
    await this.$nextTick()
    console.log(this.$el.textContent) // 'updated'
}

2
只需在“您的”说明顶部添加原始作者和链接。
Renan Cidale

1
多么惊人的解释!非常感谢您的时间和精力。
Muaath Alhaddad

16

在对aactive属性(数据)进行了一些更改之后,vue重新渲染了组件之后,Next Tick基本上允许您运行一些代码。

// modify data
vm.msg = 'Hello'
// DOM not updated yet
Vue.nextTick(function () {
  // this function is called when vue has re-rendered the component.
})

// usage as a promise (2.1.0+, see note below)
Vue.nextTick()
  .then(function () {
      // this function is called when vue has re-rendered the component.
})

从Vue.js文档中:

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

在此处了解更多信息。


2
更新方式如何?这是我不了解的。如果我更新vm.msg,则dom已经更新,因为有一个新文本“ hello” ..那么,我该如何再次更新呢?您可以用一个例子举一个小提琴吗?谢谢
hidar

好的,我将编辑答案,然后尝试进一步解释。
Daksh Miglani

@hidar您可以在必须进行多次更新但要在不同的dom周期显式呈现彼此的情况下使用它
Daksh Miglani

它不是允许您本身更新 DOM,而是在受到Vue所做的更改影响/修改后(因为您更改了反应性属性值)而对其进行任何操作(即更新,从中读取信息等)等)。
zenw0lf

这是使其变得更简单的示例。
Daksh Miglani

7

为了使Pranshat的有关使用nextTick和setTimeout的,更加明确的区别答案,我已付出他的小提琴: 这里

mounted() {    
  this.one = "One";
 
  setTimeout(() => {
    this.two = "Two"
  }, 0);
  
  //this.$nextTick(()=>{
  //this.two = "Two"
  //})}

您可以在小提琴中看到,使用setTimeOut时,一旦安装组件,然后适应更改,初始数据将非常短暂地闪烁。而使用nextTick时,数据被劫持,更改,然后呈现给浏览器。因此,浏览器甚至在不了解旧数据的情况下也显示了更新的数据。希望能一举解决两个概念。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.