什么是nextTick或它在VueJs中做了什么

时间:2017-12-04 13:15:33

标签: vue.js vuejs2

我阅读了文档,但我无法理解。我知道什么数据,计算,观察,方法,但nextTick()在vuejs中使用的是什么?

5 个答案:

答案 0 :(得分:75)

nextTick允许您在更改数据后执行某些操作,并且VueJS已根据您的数据更改更新了DOM,但在浏览器在页面上更改了这些更改之前。

通常,devs use native JavaScript function 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.$nextTick替换为setTimeout

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

重新加载浏览器。在看到Two之前,您会看到Three

将此小提琴检查到see it live

那是因为,Vue将DOM更新为Two,控制了浏览器。浏览器显示Two。然后,调用你的回调。 Vue将DOM更新为Three。哪个浏览器再次显示。

nextTick。 Vue将DOM更新为Two。叫你的回调。 Vue将DOM更新为Three。然后控制浏览器。并且,浏览器显示Three

希望很清楚。

要了解Vue如何实现这一点,您需要了解Event Loopmicrotasks的概念。

一旦您明确了这些概念(呃),请检查source code for nextTick

答案 1 :(得分:8)

下一个Tick基本上允许你在vue重新渲染组件之后运行一些代码,当你对一个被动属性(数据)做了一些更改。

// 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更新后立即使用它。

详细了解here

答案 2 :(得分:5)

为了让Pranshat回答有关使用nextTick和setTimeout之间的区别,更明确一点,我已经分享了他的小提琴: here

mounted() {    
  this.one = "One";

  setTimeout(() => {
    this.two = "Two"
  }, 0);

  //this.$nextTick(()=>{
  //this.two = "Two"
  //})}

你可以在小提琴中看到,当使用setTimeOut时,一旦组件被安装,初始数据会非常短暂地闪烁,然后再适应变化。然而,当使用nextTick时,数据在渲染到浏览器之前被劫持,更改。因此,浏览器显示更新的数据,甚至不知道旧的。 希望一举清除这两个概念。

答案 3 :(得分:2)

<块引用>

我已经创建了一个有用的演示,我们可以在 Vuejs 中使用 nextTick 的情况下,如果您想在 DOM 更新后立即更新或运行某些内容,请参阅 addMessage 函数,其中我正在调用另一个函数,其中我正在使用 nextTick 函数更新滚动以查看最新消息。

<!DOCTYPE html>
<html>
    <head>
        <title>CDN VUE 3</title>
    </head>
    <body>
        <div id="app">
        <div ref="scrolledList" style="height: 100px; width: 150px; border:1px solid red; overflow: auto; margin-bottom: 15px; padding: 5px;">
           <ul ref="scrolledHeight" style="margin: 0; padding: 0;">
               <li v-for="msg in messages">
                   {{msg}}
               </li>               
           </ul>
        </div>
           <input type="text" placeholder="Add Message" v-model="message" />
           <button @click="addMessage" @keyup.enter="addMessage"> Add Message</button>
        </div>
        <script src="https://unpkg.com/vue@next"></script>
        <script>
            Vue.createApp({
                data() {
                    return {
                       message: '',
                       messages: [1,2,3,4,5,6,7,8,9,10]
                    }
                },
                mounted() {
                    this.updateScrollNextTick()
                },
                methods: {
                    addMessage() {
                        if(this.message == ''){
                            return
                        }
                        this.messages.push(this.message)
                        this.message = ""
                        this.updateScrollNextTick()
                    },
                    updateScrollNextTick () {
                        this.$nextTick( () => {
                            let scrolledHeight = this.$refs.scrolledHeight.clientHeight
                            this.$refs.scrolledList.scrollTo({
                                behavior: 'smooth',
                                top: scrolledHeight
                            })
                        })
                    }
                },
            })
            .mount("#app")
        </script>
    </body>
</html>

答案 4 :(得分:1)

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'
}

The content has been taken fromAdriàFontcuberta