Qu'est-ce que nextTick ou que fait-il dans VueJs

104

J'ai lu la documentation, mais je ne peux pas la comprendre. Je sais ce que font les données, les calculs, la surveillance, les méthodes mais à quoi nextTick()servent-elles dans vuejs?

Hidar
la source
17
Le concept clé à comprendre est que le DOM est mis à jour de manière asynchrone . Lorsque vous modifiez une valeur dans Vue, la modification n'est pas immédiatement rendue dans le DOM. Au lieu de cela, Vue met en file d'attente une mise à jour du DOM puis, sur une minuterie, met à jour le DOM. Normalement, cela se produit si vite que cela ne fait aucune différence, mais, parfois, vous devez mettre à jour le DOM rendu après que Vue l'a rendu, ce que vous ne pouvez pas faire immédiatement dans une méthode car la mise à jour n'a pas eu lieu. encore. Dans ces cas, vous utiliseriez nextTick. Documenté ici .
Bert
En complément de ce que @Bert a dit dans https://stackoverflow.com/q/47634258/9979046 ci-dessus, le nextTick () sera utilisé dans les tests unitaires, lorsque vous devez vérifier si un élément existe dans DOM (HTML), par exemple, si vous obtenez des informations sur une requête Axios.
Oscar Alencar

Réponses:

139

nextTick vous permet de faire quelque chose après avoir modifié les données et que VueJS a mis à jour le DOM en fonction de vos modifications de données, mais avant que le navigateur n'ait rendu celles-ci modifiées sur la page.

Normalement, les développeurs utilisent la fonction JavaScript native setTimeout pour obtenir un comportement similaire. Mais, utiliser setTimeoutabandonne le contrôle sur le navigateur avant qu'il ne vous redonne le contrôle via votre rappel.

Disons que vous avez modifié certaines données. Vue met à jour le DOM en fonction des données. Notez que les modifications du DOM ne sont pas encore rendues à l'écran par le navigateur. Si vous avez utilisé nextTick, votre rappel est appelé maintenant. Ensuite, le navigateur met à jour la page. Si vous utilisiez setTimeout, votre rappel ne serait appelé que maintenant.

Vous pouvez visualiser ce comportement en créant un petit composant comme le suivant:

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

Exécutez votre serveur local. Vous verrez le message Threes'afficher.

Maintenant, remplacez votre this.$nextTickparsetTimeout

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

Rechargez le navigateur. Vous verrez Two, avant de voir Three.

Vérifiez ce violon pour le voir en direct

C'est parce que Vue a mis à jour le DOM Two, a donné le contrôle au navigateur. Navigateur affiché Two. Ensuite, j'ai appelé votre rappel. Vue a mis à jour le DOM en Three. Ce que le navigateur a affiché à nouveau.

Avec nextTick. Vue a mis à jour le DOM vers Two. J'ai appelé votre rappel. Vue a mis à jour le DOM en Three. Puis a donné le contrôle au navigateur. Et, le navigateur s'affiche Three.

J'espère que c'était clair.

Pour comprendre comment Vue implémente cela, vous devez comprendre le concept de boucle d'événement et de microtâches .

Une fois que vous avez ces concepts clairs (euh), vérifiez le code source de nextTick .

Prashant
la source
4
Une chose que je ne comprends pas, c'est que lorsque vous dites, "vue met à jour les données", faites-vous référence à la mise à jour faite avec ex: this.name = 'foo'ou faites-vous référence à l'injection d'éléments html dans la page?
hidar
Je ne vois nulle part dans l'historique de cette question où il dit "vue met à jour les données" ... Il dit "Vue met à jour le DOM en fonction des données". Cela signifie que lorsque vous définissez des données via this.name = 'foo'vue, met à jour le modèle d'objet de document pour refléter les modifications apportées aux données en fonction du modèle et des fonctions que vous configurez.
ADJenks le
24

Le contenu a été tiré de By Adrià Fontcuberta

La documentation de Vue dit:

Vue.nextTick ([rappel, contexte])

Reportez le rappel à exécuter après le prochain cycle de mise à jour du DOM. Utilisez-le immédiatement après avoir modifié certaines données pour attendre la mise à jour du DOM.

Hmm ..., si cela vous semble intimidant au début, ne vous inquiétez pas, je vais essayer de l'expliquer le plus simplement possible. Mais d'abord, il y a 2 choses que vous devez savoir:

  1. Son utilisation est rare. Comme une de ces cartes magiques argentées. J'ai écrit plusieurs Vueapplications et suis tombé sur nextTick () une ou deux fois.

  2. C'est plus facile à comprendre une fois que vous avez vu de vrais cas d'utilisation. Une fois que vous avez eu l'idée, la peur disparaîtra et vous aurez un outil pratique sous votre ceinture.

Allons-y, alors.

Comprendre $ nextTick

Nous sommes des programmeurs, n'est-ce pas? Nous utiliserons notre approche bien-aimée de division et de conquête pour essayer de traduire la description .nextTick()petit à petit. Cela commence par:

Différer le rappel

Ok, maintenant nous savons qu'il accepte un rappel. Donc ça ressemble à ça:

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

Génial. Ce rappel est différé (c'est ainsi que les millénaires disent retardé) jusqu'à…

le prochain cycle de mise à jour du DOM.

D'accord. Nous savons que Vue effectue les mises à jour DOM de manière asynchrone . Il propose un moyen de conserver ces mises à jour «stockées» jusqu'à ce qu'il ait besoin de les appliquer. Il crée une file d'attente de mises à jour et la vide si nécessaire. Ensuite, le DOM est «patché» et mis à jour vers sa dernière version.

Quoi?

Laissez-moi réessayer: imaginez que votre composant fasse quelque chose de vraiment essentiel et intelligent comme this.potatoAmount = 3. Vue ne rendra pas automatiquement le composant (et donc le DOM). Il mettra en file d'attente la modification requise. Ensuite, au «tick» suivant (comme dans une horloge), la file d'attente est vidée et la mise à jour est appliquée. Tada!

D'accord! Nous savons donc que nous pouvons utiliser nextTick()pour passer une fonction de rappel qui est exécutée juste après la définition des données et la mise à jour du DOM.

Comme je l'ai dit plus tôt… pas si souvent. L'approche du «flux de données» qui anime Vue, React et l'autre de Google, que je ne mentionnerai pas, la rend inutile la plupart du temps. Pourtant, nous devons parfois attendre que certains éléments apparaissent / disparaissent / soient modifiés dans le DOM. C'est à ce moment que nextTick est utile.

Utilisez-le immédiatement après avoir modifié certaines données pour attendre la mise à jour du DOM.

Exactement! C'est la dernière partie de la définition que la documentation Vue nous a fournie. Dans notre rappel, le DOM a été mis à jour afin que nous puissions interagir avec la version «la plus mise à jour» de celui-ci.

Prouve le

OK OK. Consultez la console et vous verrez que la valeur de nos données est mise à jour uniquement dans le rappel 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 cas d'utilisation

Essayons de définir un cas d'utilisation utile pour nextTick .

Imaginez que vous deviez effectuer une action lorsqu'un composant est monté. MAIS! pas seulement le composant. Vous devez également attendre que tous ses enfants soient montés et disponibles dans le DOM. Zut! Notre crochet monté ne garantit pas le rendu de l'ensemble de l'arborescence des composants.

Si seulement nous avions un outil pour attendre le prochain cycle de mise à jour du DOM…

Hahaa:

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

En un mot

Donc: nextTickest un moyen confortable d'exécuter une fonction après que les données ont été définies et que le DOM a été mis à jour.

Vous devez attendre le DOM, peut-être parce que vous devez effectuer une transformation ou vous devez attendre qu'une bibliothèque externe charge son contenu? Ensuite, utilisez nextTick.

Certaines personnes utilisent également nextTick dans leurs tests unitaires pour s'assurer que les données ont été mises à jour. De cette façon, ils peuvent tester la «version mise à jour» du composant.

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

Ne t'inquiète pas. Les deux sont (presque) les mêmes. Vue.nextTick()fait référence à la méthode API globale, tandis que vm.$nextTick()est une méthode d'instance. La seule différence est que vm.$nextTickn'accepte pas un contexte comme deuxième paramètre. Il est toujours lié àthis (également appelé instance elle-même).

Un dernier morceau de fraîcheur

Notez que nextTickretourne a Promise, afin que nous puissions aller complètement cool avec async/awaitet améliorer l'exemple:

async mounted () {
    this.message = 'updated'
    console.log(this.$el.textContent) // 'not updated'
    await this.$nextTick()
    console.log(this.$el.textContent) // 'updated'
}
Humoyun Ahmad
la source
2
Ajoutez simplement l'auteur original et le lien, en haut de "votre" explication.
Renan Cidale le
1
Quelle explication incroyable! Merci beaucoup pour votre temps et vos efforts.
Muaath Alhaddad
16

Next Tick vous permet essentiellement d'exécuter du code, une fois que la vue a re-rendu le composant lorsque vous avez apporté des modifications à la propriété réactive (données).

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

À partir de la documentation Vue.js:

Reportez le rappel à exécuter après le prochain cycle de mise à jour du DOM. Utilisez-le immédiatement après avoir modifié certaines données pour attendre la mise à jour du DOM.

Pour en savoir plus, cliquez ici .

Daksh Miglani
la source
2
le mettre à jour comment? c'est ce que je ne comprends pas. si je mets à jour vm.msg alors le dom est déjà mis à jour car il y a un nouveau texte «bonjour» .. alors comment puis-je le mettre à jour à nouveau? pouvez-vous poster un violon avec un exemple pls? merci
hidar
d'accord, je modifierai la réponse et j'essaierai de l'expliquer davantage.
Daksh Miglani
@hidar, vous pouvez l'utiliser dans des situations où vous devez effectuer plusieurs mises à jour, mais que vous souhaitez effectuer un rendu explicite à différents cycles dom
Daksh Miglani
Ce n'est pas pour vous permettre de mettre à jour le DOM en soi, mais pour faire quoi que ce soit avec lui (que ce soit mettre à jour, lire des informations à partir de celui-ci, etc.) après qu'il a été affecté / modifié par des changements effectués par Vue (parce que vous avez changé une valeur de propriété réactive , etc).
zenw0lf
C'était un exemple pour simplifier les choses.
Daksh Miglani
7

Pour rendre la réponse de Pranshat sur la différence entre l'utilisation de nextTick et setTimeout, plus explicite, j'ai bifurqué son violon: ici

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

Vous pouvez voir dans le violon que lors de l'utilisation de setTimeOut, les données initiales clignotent très brièvement une fois le composant monté avant d'adapter le changement. Alors que, lors de l'utilisation de nextTick, les données sont détournées, modifiées, avant d'être rendues dans le navigateur. Ainsi, le navigateur affiche les données mises à jour sans même aucune connaissance de l'ancienne. J'espère que cela efface les deux concepts d'un seul coup.

Wale
la source