Was ist nextTick oder was macht es in VueJs?


103

Ich habe die Dokumente gelesen, kann sie aber nicht verstehen. Ich weiß, was Daten, berechnete, beobachtete und Methoden tun, aber wofür werden sie nextTick()in vuejs verwendet?


16
Das zu verstehende Schlüsselkonzept ist, dass das DOM asynchron aktualisiert wird . Wenn Sie einen Wert in Vue ändern, wird die Änderung nicht sofort in das DOM übertragen. Stattdessen stellt Vue ein DOM-Update in die Warteschlange und aktualisiert dann auf einem Timer das DOM. Normalerweise geschieht dies so schnell, dass es keinen Unterschied macht, aber manchmal müssen Sie das gerenderte DOM aktualisieren, nachdem Vue es gerendert hat, was Sie in einer Methode nicht sofort tun können, da das Update nicht stattgefunden hat noch. In diesen Fällen würden Sie verwenden nextTick. Hier dokumentiert .
Bert

Ergänzend zu den obigen Ausführungen von @Bert in https://stackoverflow.com/q/47634258/9979046 wird nextTick () in Komponententests verwendet, wenn Sie beispielsweise überprüfen müssen, ob ein Element in DOM (HTML) vorhanden ist. wenn Sie Informationen zu einer Axios-Anfrage erhalten.
Oscar Alencar

Antworten:


137

Mit nextTick können Sie etwas tun, nachdem Sie die Daten geändert haben und VueJS das DOM basierend auf Ihrer Datenänderung aktualisiert hat, aber bevor der Browser die auf der Seite geänderten Daten gerendert hat.

Normalerweise verwenden Entwickler die native JavaScript-Funktion setTimeout , um ein ähnliches Verhalten zu erzielen. Wenn Sie jedoch verwenden, wird setTimeoutdie Kontrolle an den Browser abgegeben, bevor Sie die Kontrolle über Ihren Rückruf zurückerhalten.

Angenommen, Sie haben einige Daten geändert. Vue aktualisiert das DOM basierend auf den Daten. Allerdings werden die DOM-Änderungen vom Browser noch nicht auf dem Bildschirm gerendert. Wenn Sie verwendet haben nextTick, wird Ihr Rückruf jetzt aufgerufen. Anschließend aktualisiert der Browser die Seite. Wenn Sie verwendet haben setTimeout, wird Ihr Rückruf erst jetzt angerufen.

Sie können dieses Verhalten visualisieren, indem Sie eine kleine Komponente wie die folgende erstellen:

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

Führen Sie Ihren lokalen Server aus. Sie sehen, dass die Nachricht Threeangezeigt wird.

Ersetzen Sie jetzt Ihre this.$nextTickdurchsetTimeout

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

Laden Sie den Browser neu. Sie werden sehen Two, bevor Sie sehen Three.

Überprüfen Sie diese Geige, um sie live zu sehen

Das liegt daran, dass Vue das DOM aktualisiert Twohat und dem Browser die Kontrolle gegeben hat. Browser angezeigt Two. Dann rief Ihr Rückruf. Vue hat das DOM auf aktualisiert Three. Was der Browser wieder anzeigt.

Mit nextTick. Vue udpierte das DOM zu Two. Rief deinen Rückruf an. Vue hat das DOM auf aktualisiert Three. Dann gab dem Browser die Kontrolle. Und der Browser wird angezeigt Three.

Hoffe es war klar.

Um zu verstehen, wie Vue dies implementiert, müssen Sie das Konzept der Ereignisschleife und der Mikrotasks verstehen .

Wenn Sie diese Konzepte gelöscht haben , überprüfen Sie den Quellcode auf nextTick .


4
Eine Sache, die ich nicht verstehe, ist, wenn Sie sagen: "vue aktualisiert die Daten". Beziehen Sie sich auf die mit ex: aktualisierte Aktualisierung: this.name = 'foo'oder beziehen Sie sich auf die Einfügung von HTML-Elementen in die Seite?
Hidar

Ich sehe nirgendwo in der Geschichte dieser Frage, wo er sagt "Vue aktualisiert die Daten" ... Er sagt "Vue aktualisiert DOM basierend auf den Daten". Dies bedeutet, dass beim Festlegen von Daten über this.name = 'foo'vue das Dokumentobjektmodell aktualisiert wird, um die an den Daten vorgenommenen Änderungen basierend auf der von Ihnen konfigurierten Vorlage und den Funktionen widerzuspiegeln.
ADJenks

23

Der Inhalt wurde von Adrià Fontcuberta übernommen

Vue-Dokumentation sagt:

Vue.nextTick ([Rückruf, Kontext])

Verschieben Sie den Rückruf, der nach dem nächsten DOM-Aktualisierungszyklus ausgeführt werden soll. Verwenden Sie es sofort, nachdem Sie einige Daten geändert haben, um auf das DOM-Update zu warten.

Hmm ..., wenn es sich zuerst einschüchternd anfühlt, mach dir keine Sorgen, ich werde versuchen, es so einfach wie möglich zu erklären. Aber zuerst sollten Sie zwei Dinge wissen:

  1. Seine Verwendung ist ungewöhnlich. Wie eine dieser silbernen Zauberkarten. Ich habe mehrere VueApps geschrieben und bin ein- oder zweimal auf nextTick () gestoßen.

  2. Es ist einfacher zu verstehen, wenn Sie einige echte Anwendungsfälle gesehen haben. Nachdem Sie auf die Idee gekommen sind, wird die Angst verschwinden und Sie haben ein handliches Werkzeug unter Ihrem Gürtel.

Dann lass uns loslegen.

$ NextTick verstehen

Wir sind Programmierer, nicht wahr? Wir werden unseren geliebten Divide and Conquer-Ansatz verwenden, um zu versuchen, die Beschreibung von .nextTick()Stück für Stück zu übersetzen . Es beginnt mit:

Verschieben Sie den Rückruf

Ok, jetzt wissen wir, dass es einen Rückruf akzeptiert. So sieht es aus:

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

Toll. Dieser Rückruf wird verschoben (so sagen Millenials verzögert), bis…

der nächste DOM-Aktualisierungszyklus.

In Ordnung. Wir wissen, dass Vue DOM-Updates asynchron durchführt . Es bietet eine Möglichkeit, diese Updates so lange „gespeichert“ zu halten, bis sie angewendet werden müssen. Es erstellt eine Warteschlange mit Updates und löscht diese bei Bedarf. Anschließend wird das DOM „gepatcht“ und auf die neueste Version aktualisiert.

Was?

Lassen Sie es mich noch einmal versuchen: Stellen Sie sich vor, Ihre Komponente macht etwas wirklich Wesentliches und Kluges, als würde this.potatoAmount = 3.Vue die Komponente (und damit das DOM) nicht automatisch neu rendern. Die erforderliche Änderung wird in die Warteschlange gestellt. Dann wird beim nächsten „Tick“ (wie bei einer Uhr) die Warteschlange geleert und die Aktualisierung angewendet. Tada!

In Ordnung! Wir wissen also, dass wir nextTick()eine Rückruffunktion übergeben können, die direkt ausgeführt wird, nachdem die Daten festgelegt und das DOM aktualisiert wurden.

Wie ich schon sagte ... nicht so oft. Der "Datenfluss" -Ansatz, der Vue, React und den anderen von Google antreibt, den ich nicht erwähne, macht ihn die meiste Zeit unnötig. Manchmal müssen wir jedoch warten, bis einige Elemente im DOM erscheinen / verschwinden / geändert werden. Dies ist der Zeitpunkt, an dem nextTick nützlich ist.

Verwenden Sie es sofort, nachdem Sie einige Daten geändert haben, um auf das DOM-Update zu warten.

Genau! Dies ist die letzte Definition, die uns Vue-Dokumente zur Verfügung gestellt haben. In unserem Rückruf wurde das DOM aktualisiert, damit wir mit der „aktuellsten“ Version interagieren können.

Beweise es

Okay okay. Wenn Sie sich die Konsole ansehen, werden Sie feststellen, dass der Wert unserer Daten nur innerhalb des Rückrufs von nextTick aktualisiert wird:

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>

Ein Anwendungsfall

Versuchen wir, einen nützlichen Anwendungsfall für zu definieren nextTick.

Stellen Sie sich vor, Sie müssen eine Aktion ausführen, wenn eine Komponente bereitgestellt wird. ABER! nicht nur die Komponente. Sie müssen auch warten, bis alle untergeordneten Elemente im DOM bereitgestellt und verfügbar sind. Verdammt! Unser montierter Hook garantiert nicht, dass der gesamte Komponentenbaum gerendert wird.

Wenn wir nur ein Tool hätten, um auf den nächsten DOM-Aktualisierungszyklus zu warten ...

Hahaa:

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

In einer Nussschale

Also: nextTickist eine bequeme Möglichkeit, eine Funktion auszuführen, nachdem die Daten festgelegt und das DOM aktualisiert wurden.

Sie müssen auf das DOM warten, vielleicht weil Sie eine Transformation durchführen müssen, oder Sie müssen warten, bis eine externe Bibliothek ihre Inhalte geladen hat? Verwenden Sie dann nextTick.

Einige Benutzer verwenden nextTick auch in ihren Komponententests, um sicherzustellen, dass die Daten aktualisiert wurden. Auf diese Weise können sie die „aktualisierte Version“ der Komponente testen.

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

Mach dir keine Sorgen. Beide sind (fast) gleich. Vue.nextTick()verweist auf die globale API-Methode, während vm.$nextTick()es sich um eine Instanzmethode handelt. Der einzige Unterschied besteht darin, dass vm.$nextTickkein Kontext als zweiter Parameter akzeptiert wird. Es ist immer gebunden this(auch als Instanz selbst bekannt).

Ein letztes Stück Coolness

Beachten Sie, dass nextTicka zurückgegeben wird Promise, damit wir async/awaitdas Beispiel vollständig abkühlen und verbessern können:

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

2
Fügen Sie einfach den Originalautor und den Link oben in "Ihrer" Erklärung hinzu.
Renan Cidale

1
Was für eine erstaunliche Erklärung! Vielen Dank für Ihre Zeit und Mühe.
Muaath Alhaddad

16

Mit Next Tick können Sie im Grunde genommen Code ausführen, nachdem der Vue die Komponente neu gerendert hat, nachdem Sie einige Änderungen an der reaktiven Eigenschaft (Daten) vorgenommen haben.

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

Aus der Vue.js-Dokumentation:

Verschieben Sie den Rückruf, der nach dem nächsten DOM-Aktualisierungszyklus ausgeführt werden soll. Verwenden Sie es sofort, nachdem Sie einige Daten geändert haben, um auf das DOM-Update zu warten.

Lesen Sie hier mehr darüber .


2
Update wie? das verstehe ich nicht. Wenn ich vm.msg aktualisiere, ist der Dom bereits aktualisiert, da es einen neuen Text "Hallo" gibt. Wie kann ich ihn also erneut aktualisieren? Kannst du eine Geige mit einem Beispiel ps posten? danke
hidar

Okay, ich werde die Antwort bearbeiten und versuchen, sie weiter zu erklären.
Daksh Miglani

@hidar Sie können es in Situationen verwenden, in denen Sie mehrere Updates durchführen müssen, aber Sie möchten sich explizit in verschiedenen Dom-Zyklen rendern
Daksh Miglani

Es dient nicht dazu, das DOM per se zu aktualisieren , sondern etwas damit zu tun (sei es aktualisieren, Informationen daraus lesen usw.), nachdem es durch von Vue vorgenommene Änderungen beeinflusst / geändert wurde (weil Sie einen reaktiven Eigenschaftswert geändert haben , etc).
Zenw0lf

Das war ein Beispiel, um es einfacher zu machen.
Daksh Miglani

7

Um Pranshats Antwort auf den Unterschied zwischen der Verwendung von nextTick und setTimeout deutlicher zu machen, habe ich seine Geige gegabelt: hier

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

Sie können in der Geige sehen, dass bei Verwendung von setTimeOut die Anfangsdaten sehr kurz blinken, sobald die Komponente bereitgestellt wird, bevor die Änderung angepasst wird. Bei Verwendung von nextTick werden die Daten vor dem Rendern in den Browser entführt und geändert. Der Browser zeigt also die aktualisierten Daten an, ohne die alten zu kennen. Hoffe, das klärt die beiden Konzepte auf einen Schlag.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.