170 votes

Qu'est-ce que nextTick et que fait-il dans Vue.js ?

Je lis les docs mais je ne peux toujours pas le comprendre.

Je sais ce que data , computed , watch , methods faire, mais ce qui est nextTick() utilisé dans Vue.js ?

36 votes

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 rendu dans le DOM. Au lieu de cela, Vue met en file d'attente une mise à jour du DOM et ensuite, sur une minuterie, met à jour le DOM. Normalement, cela se produit si rapidement que cela ne fait pas de différence, mais, parfois, vous devez mettre à jour le DOM rendu après que Vue l'ait rendu, ce que vous ne pouvez pas faire immédiatement dans une méthode parce que la mise à jour n'a pas encore eu lieu. Dans ces cas, vous utiliserez nextTick . Documenté ici .

1 votes

Complétant ce que @Bert a dit dans https://stackoverflow.com/q/47634258/9979046 ci-dessus, la fonction nextTick() sera utilisée dans les tests unitaires, lorsque vous devez vérifier si un élément existe dans le DOM (HTML), par exemple, si vous obtenez des informations sur une requête Axios.

0 votes

Pourquoi ai-je l'impression que nextTick est quelque chose comme const nextTick = (callback, context) => { setTimeout(callback.bind(context), 0); }; ?

264voto

Prashant Points 3230

Tout est question de timing

nextTick vous permet d'exécuter du code après vous avez modifié certaines données et Vue.js a mis à jour le DOM virtuel sur la base de vos modifications de données, mais antes de le navigateur a rendu cette modification sur la page.

Normalement, Les développeurs utilisent la fonction JavaScript native setTimeout pour obtenir un comportement similaire, mais en utilisant setTimeout cède le contrôle au navigateur antes de il vous rend le contrôle (en appelant votre callback).

Exemple

Disons que vous avez modifié certaines données ; Vue met alors à jour le vDOM en fonction de cette modification des données (les modifications ne sont pas encore rendues à l'écran par le navigateur).

Si vous avez utilisé nextTick à ce stade, votre callback serait appelé immédiatement, et le navigateur mettrait à jour la page après la fin de l'exécution de ce callback.

Si vous utilisez plutôt setTimeout le navigateur aurait alors la possibilité de mettre à jour la page, et puis votre callback sera appelé.

Vous pouvez visualiser ce comportement en créant un petit composant comme le suivant :
(Vérification <a href="https://jsfiddle.net/prashantpalikhe/50wL7mdz/80945/" rel="nofollow noreferrer">ce violon </a>pour le voir en direct)

<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 "Trois" s'afficher.

Maintenant, remplacez this.$nextTick avec setTimeout :

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

Rechargez le navigateur. Vous verrez "Deux" avant de voir "Trois".

C'est parce que, avec setTimeout :

  1. Vue a mis à jour le vDOM pour dire "Deux".
  2. Vue a donné le contrôle au navigateur
  3. Le navigateur a affiché "Deux"
  4. Le callback a été appelé
  5. Vue a mis à jour le vDOM pour dire "Trois".
  6. Vue a donné le contrôle au navigateur
  7. Le navigateur a affiché "Trois"

Mais avec nextTick nous sautons les étapes 2 et 3 ! Au lieu de passer le contrôle après la première mise à jour du vDOM, Vue appelle la callback immédiatement ce qui empêche le navigateur de se mettre à jour tant que la fonction de rappel n'est pas terminée. Dans cet exemple, cela signifie que "Deux" n'est jamais réellement affiché.

Pour comprendre comment Vue implémente cela, vous devez comprendre le concept de l'interface JavaScript. Boucle d'événement y microtâches .

Une fois que vous avez clarifié ces concepts, vérifiez les éléments suivants code source pour nextTick .

4 votes

Une chose que je ne comprends pas, c'est que lorsque vous dites "Vue met à jour les données", vous faites référence à la mise à jour effectuée avec ex : this.name = 'foo' ou faites-vous référence à l'injection d'éléments html dans la page ?

1 votes

Je ne vois nulle part dans l'historique de cette question où il dit "Vue met à jour les données"... Il dit bien "Vue met à jour le DOM en fonction des données". Ce qui signifie que lorsque vous définissez les données via this.name = 'foo' Vue met à jour le modèle d'objet du document pour refléter les modifications apportées aux données en fonction du modèle et des fonctions que vous configurez.

0 votes

Cette réponse m'a permis de comprendre comment et quand utiliser nexttick et setTimeOut. Merci.

44voto

Humoyun Points 2120

Le contenu est tiré de Par Adrià Fontcuberta

La documentation de Vue dit :

Vue.nextTick( [callback, context] )

Diffère le callback pour qu'il soit exécuté après le prochain cycle de mise à jour du DOM. Utilisez immédiatement après avoir modifié des données pour attendre la mise à jour du DOM. soit mis à jour.

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

  1. Son usage est peu commun. Comme une de ces cartes magiques en argent. J'ai écrit plusieurs Vue et je suis tombé sur nextTick() une ou deux fois.

  2. C'est plus facile à comprendre une fois que vous avez vu des cas d'utilisation réels. Une fois que vous aurez saisi l'idée, la crainte disparaîtra et vous aurez un outil pratique à votre disposition.

Allons-y, alors.

Comprendre $nextTick

Nous sommes des programmeurs, n'est-ce pas ? Nous allons utiliser notre chère approche "diviser pour mieux régner" pour essayer de traduire la description de .nextTick() petit à petit. Ça commence par :

Différer le rappel

Ok, maintenant on sait qu'il accepte un callback. Donc ça ressemble à ça :

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

Super. Ce rappel est différé (c'est comme ça que les millenials disent différé) jusqu'à

le prochain cycle de mise à jour du DOM.

Ok. Nous savons que Vue effectue les mises à jour du DOM de manière asynchrone . Il dispose d'un moyen de garder 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 lorsque cela est nécessaire. Le DOM est alors "patché" et mis à jour dans sa dernière version.

Quoi ?

Laissez-moi essayer à nouveau : Imaginez que votre composant fasse quelque chose de vraiment essentiel et intelligent comme this.potatoAmount = 3. Vue ne rendra pas le composant (et donc le DOM) automatiquement. Il mettra en file d'attente la modification requise. Puis, au prochain "tic-tac" (comme dans une horloge), la file d'attente est vidée et la mise à jour est appliquée. Et voilà !

Ok ! Donc nous savons que nous pouvons utiliser nextTick() pour passer une fonction de rappel qui est exécutée juste après les données sont définies et le DOM a été mis à jour.

Comme je l'ai dit plus tôt pas si souvent. L'approche " 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 avons parfois besoin d'attendre que certains éléments apparaissent/disparaissent/soient modifiés dans le DOM. C'est là que nextTick s'avère utile.

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

Exactement ! C'est le dernier élément de définition que la documentation de Vue nous a fourni. A l'intérieur de notre callback, le DOM a été mis à jour afin que nous puissions interagir avec la version la plus récente de celui-ci.

Prouvez-le

Ok, ok. Regardez la console, et vous verrez que la valeur de nos données est mise à jour uniquement dans le callback 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 des cas d'utilisation utiles pour les services suivants nextTick .

Imaginez que vous ayez besoin d'exécuter 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. Mince ! Notre hook monté ne garantit pas le rendu de l'ensemble de l'arbre du composant.

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

Hahaa :

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

En bref

Donc : nextTick est 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 avez besoin d'attendre le DOM, peut-être parce que vous devez effectuer une transformation ou que vous devez attendre qu'une bibliothèque externe charge son contenu ? Utilisez alors nextTick.

Certaines personnes utilisent également nextTick dans leurs tests unitaires afin de 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 vous inquiétez pas. Les deux sont (presque) les mêmes. Vue.nextTick() fait référence à la méthode globale de l'API, tandis que vm.$nextTick() est une méthode d'instance. La seule différence est que vm.$nextTick n'accepte pas un contexte comme second paramètre. Elle est toujours liée à this (également connue comme l'instance elle-même).

Un dernier morceau de fraîcheur

Remarquez que nextTick renvoie un Promise donc on peut faire le plein de cool avec async/await et 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'
}

9 votes

Il suffit d'ajouter l'auteur original et le lien, en haut de "votre" explication.

1 votes

Quelle explication étonnante ! Merci beaucoup pour votre temps et vos efforts.

2 votes

Merde, tu viens de copier tout le message du médium. Descendu.

21voto

Daksh Miglani Points 1820

Next Tick vous permet essentiellement d'exécuter du code, après que Vue ait redessiné le composant, lorsque vous avez apporté des modifications à une 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.
    })

Extrait de la documentation de Vue.js :

Diffère le callback pour qu'il soit exécuté 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, aquí .

2 votes

Comment le mettre à jour ? c'est ce que je ne comprends pas. si je mets à jour vm.msg alors le dom est déjà mis à jour parce qu'il y a un nouveau texte ''hello'' alors comment puis-je le mettre à jour à nouveau ? pouvez-vous poster une manipulation avec un exemple pls ? merci.

0 votes

Ok, je vais éditer la réponse et je vais essayer de l'expliquer davantage.

0 votes

@hidar vous pouvez l'utiliser dans des situations où vous devez faire plusieurs mises à jour, mais vous voulez explicitement faire un rendu de chacune d'elles à des cycles dom différents.

11voto

Wale Points 623

Pour faire la réponse de Pranshat sur la différence entre utiliser nextTick y setTimeout plus explicite, j'ai fourché son violon : aquí

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

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

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

Vous pouvez voir dans l'exemple que lorsque l'on utilise l'option 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 au navigateur. Ainsi, le navigateur affiche les données mises à jour sans même avoir connaissance des anciennes. J'espère que cela clarifie les deux concepts d'un seul coup.

3voto

Dileep Pal Points 51

J'ai créé une démo utile dans quel scénario nous pouvons utiliser nextTick dans Vuejs, si vous voulez mettre à jour ou exécuter quelque chose immédiatement après les mises à jour de votre DOM, voir la fonction addMessage où j'appelle une autre fonction dans laquelle j'utilise une fonction nextTick pour mettre à jour le scroll pour voir le dernier message.

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X