¿Qué es nextTick o qué hace en VueJs?

104

Leo los documentos, pero no puedo entenderlos. Sé lo que hacen los métodos de datos, calculados, de observación, pero ¿ nextTick()para qué sirven en vuejs?

hidar
fuente
17
El concepto clave a comprender es que el DOM se actualiza de forma asincrónica . Cuando cambia un valor en Vue, el cambio no se representa inmediatamente en el DOM. En cambio, Vue pone en cola una actualización de DOM y luego, en un temporizador, actualiza el DOM. Normalmente, esto sucede tan rápido que no hace ninguna diferencia, pero, a veces, es necesario actualizar el DOM renderizado después de que Vue lo ha renderizado, lo que no puede hacer de inmediato en un método porque la actualización no ha ocurrido. todavía. En esos casos, usaría nextTick. Documentado aquí .
Bert
Complementando lo que dijo @Bert en https://stackoverflow.com/q/47634258/9979046 arriba, el nextTick () se utilizará en las pruebas unitarias, cuando necesite verificar si un elemento existe en DOM (HTML), por ejemplo, si obtiene información sobre una solicitud de Axios.
Oscar Alencar

Respuestas:

138

nextTick le permite hacer algo después de haber cambiado los datos y VueJS ha actualizado el DOM en función de su cambio de datos, pero antes de que el navegador haya presentado los cambios en la página.

Normalmente, los desarrolladores usan la función nativa de JavaScript setTimeout para lograr un comportamiento similar. Pero, el uso setTimeoutcede el control al navegador antes de que le devuelva el control a través de su devolución de llamada.

Digamos que cambió algunos datos. Vue actualiza DOM en función de los datos. Tenga en cuenta que el navegador aún no muestra los cambios en el DOM en la pantalla. Si lo utilizó nextTick, su devolución de llamada se llama ahora. Luego, el navegador actualiza la página. Si lo utiliza setTimeout, su devolución de llamada se llamará solo ahora.

Puede visualizar este comportamiento creando un pequeño componente como el siguiente:

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

Ejecute su servidor local. Verá el mensaje que Threese muestra.

Ahora, reemplace su this.$nextTickconsetTimeout

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

Vuelve a cargar el navegador. Verás Two, antes de ver Three.

Mira este violín para verlo en vivo

Eso es porque, Vue actualizó el DOM a Two, le dio control al navegador. Se muestra el navegador Two. Luego, llamó a su devolución de llamada. Vue actualizó el DOM a Three. Que el navegador volvió a mostrar.

Con nextTick. Vue actualizó el DOM a Two. Llamado a su devolución de llamada. Vue actualizó el DOM a Three. Luego le dio el control al navegador. Y se muestra el navegador Three.

Espero que haya quedado claro.

Para comprender cómo Vue implementa esto, debe comprender el concepto de Event Loop y microtasks .

Una vez que tenga esos conceptos claros (más), verifique el código fuente de nextTick .

Prashant
fuente
4
Una cosa que no entiendo es que cuando dices "vue actualiza los datos", ¿te refieres a la actualización realizada con ex: this.name = 'foo'o te refieres a la inyección de elementos html en la página?
hidar
No veo en ningún lugar del historial de esta pregunta donde diga "vue actualiza los datos" ... Sí dice "Vue actualiza DOM basado en los datos". Lo que significa que cuando configuras datos a través de this.name = 'foo'vue, se actualiza el modelo de objetos del documento para reflejar los cambios realizados en los datos según la plantilla y las funciones que configuras.
ADJenks
24

El contenido ha sido tomado de Por Adrià Fontcuberta

La documentación de Vue dice:

Vue.nextTick ([devolución de llamada, contexto])

Aplaza la ejecución de la devolución de llamada después del próximo ciclo de actualización del DOM. Úselo inmediatamente después de haber cambiado algunos datos para esperar la actualización del DOM.

Hmm ..., si te parece intimidante al principio, no te preocupes, intentaré explicártelo de la forma más sencilla posible. Pero primero hay 2 cosas que debes saber:

  1. Su uso es poco común. Como una de esas cartas mágicas plateadas. He escrito varias Vueaplicaciones y encontré nextTick () una o dos veces.

  2. Es más fácil de entender una vez que haya visto algunos casos de uso reales. Una vez que tenga la idea, el miedo desaparecerá y tendrá una herramienta útil en su haber.

Vamos a por ello, entonces.

Entendiendo $ nextTick

Somos programadores, ¿no? Usaremos nuestro amado enfoque de dividir y conquistar para tratar de traducir la descripción .nextTick()poco a poco. Empieza con:

Aplazar la devolución de llamada

Bien, ahora sabemos que acepta una devolución de llamada. Entonces se ve así:

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

Excelente. Esta devolución de llamada se aplaza (así es como los millenials dicen que se retrasa) hasta ...

el próximo ciclo de actualización del DOM.

Bueno. Sabemos que Vue realiza actualizaciones DOM de forma asincrónica . Cuenta con una forma de mantener estas actualizaciones "almacenadas" hasta que sea necesario aplicarlas. Crea una cola de actualizaciones y la vacía cuando es necesario. Luego, el DOM es "parcheado" y actualizado a su última versión.

¿Qué?

Déjame intentarlo de nuevo: imagina que tu componente hace algo realmente esencial e inteligente, como que this.potatoAmount = 3.Vue no volverá a renderizar el componente (y por lo tanto el DOM) automáticamente. Pondrá en cola la modificación requerida. Luego, en el siguiente "tic" (como en un reloj), la cola se vacía y se aplica la actualización. Tada!

¡Bueno! Entonces sabemos que podemos usar nextTick()para pasar una función de devolución de llamada que se ejecuta justo después de que se establecen los datos y se actualiza el DOM.

Como dije antes… no tan a menudo. El enfoque de "flujo de datos" que impulsa a Vue, React y el otro de Google, que no mencionaré, lo hace innecesario la mayor parte del tiempo. Sin embargo, a veces necesitamos esperar a que algunos elementos aparezcan / desaparezcan / se modifiquen en el DOM. Aquí es cuando nextTick resulta útil.

Úselo inmediatamente después de haber cambiado algunos datos para esperar la actualización del DOM.

¡Exactamente! Esta es la última pieza de definición que nos proporcionaron los documentos de Vue. Dentro de nuestra devolución de llamada, el DOM se ha actualizado para que podamos interactuar con la versión "más actualizada".

Pruébalo

Bien bien. Vea la consola y verá que el valor de nuestros datos se actualiza solo dentro de la devolución de llamada de 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>

Un caso de uso

Intentemos definir algún caso de uso útil para nextTick.

Imagine que necesita realizar alguna acción cuando se monta un componente. ¡PERO! no solo el componente. También debe esperar hasta que todos sus elementos secundarios estén montados y disponibles en el DOM. ¡Maldición! Nuestro gancho montado no garantiza que se procese todo el árbol de componentes.

Si tan solo tuviéramos una herramienta para esperar el próximo ciclo de actualización del DOM ...

Jaja:

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

En una palabra

Entonces: nextTickes una forma cómoda de ejecutar una función después de que se hayan configurado los datos y se haya actualizado el DOM.

¿Necesita esperar al DOM, tal vez porque necesita realizar alguna transformación o necesita esperar a que una biblioteca externa cargue sus cosas? Luego use nextTick.

Algunas personas también usan nextTick en sus pruebas unitarias como una forma de asegurarse de que los datos se hayan actualizado. De esta manera, pueden probar la "versión actualizada" del componente.

Vue.nextTick () o vm. $ NextTick ()?

No se preocupe. Ambos son (casi) iguales. Vue.nextTick()se refiere al método API global, mientras que vm.$nextTick()es un método de instancia. La única diferencia es que vm.$nextTickno acepta un contexto como segundo parámetro. Siempre está vinculado a this(también conocido como la propia instancia).

Un último trozo de frescura

Observe que nextTickdevuelve unPromise , por lo que podemos enfriarnos completamente async/awaity mejorar el ejemplo:

async mounted () {
    this.message = 'updated'
    console.log(this.$el.textContent) // 'not updated'
    await this.$nextTick()
    console.log(this.$el.textContent) // 'updated'
}
Humoyun Ahmad
fuente
2
Simplemente agregue el autor original y el enlace, en la parte superior de "su" explicación.
Renan Cidale
1
¡Qué explicación más asombrosa! Muchas gracias por su tiempo y esfuerzo.
Muaath Alhaddad
16

Next Tick básicamente le permite ejecutar algún código, después de que vue haya vuelto a renderizar el componente cuando haya realizado algunos cambios en la propiedad reactiva (datos).

// 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.
})

De la documentación de Vue.js:

Aplaza la ejecución de la devolución de llamada después del próximo ciclo de actualización del DOM. Úselo inmediatamente después de haber cambiado algunos datos para esperar la actualización del DOM.

Lea más sobre esto aquí .

Daksh Miglani
fuente
2
actualizarlo como? esto es lo que no entiendo. si actualizo vm.msg, entonces el dom ya está actualizado porque hay un nuevo texto "hola" ... entonces, ¿cómo puedo actualizarlo de nuevo? ¿Pueden publicar un violín con un ejemplo por favor? Gracias
hidar
está bien, editaré la respuesta e intentaré explicarla más.
Daksh Miglani
@hidar, puede usarlo en situaciones en las que tiene que hacer varias actualizaciones, pero desea renderizar explícitamente entre sí en diferentes ciclos de dom
Daksh Miglani
No es para permitirle actualizar el DOM per se, sino para hacer cualquier cosa con él (ya sea actualizar, leer información de él, etc.) después de que se haya visto afectado / modificado por los cambios realizados por Vue (porque cambió un valor de propiedad reactiva , etc.).
zenw0lf
Ese fue un ejemplo para hacerlo más simple.
Daksh Miglani
7

Para hacer que la respuesta de Pranshat sobre la diferencia entre usar nextTick y setTimeout, sea más explícita, he bifurcado su violín: aquí

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

Puede ver en el violín que cuando se usa setTimeOut, los datos iniciales parpadean muy brevemente una vez que se monta el componente antes de adaptar el cambio. Mientras que, cuando se usa nextTick, los datos se secuestran, cambian, antes de procesarlos en el navegador. Entonces, el navegador muestra los datos actualizados sin siquiera tener conocimiento de los antiguos. Espero que aclare los dos conceptos de una sola vez.

Wale
fuente