Cos'è nextTick o cosa fa in VueJs


104

Ho letto i documenti, ma non riesco a capirlo. So cosa fanno i dati, calcolati, nextTick()guardati , ma a cosa servono in vuejs?


17
Il concetto chiave da comprendere è che il DOM viene aggiornato in modo asincrono . Quando modifichi un valore in Vue, la modifica non viene immediatamente renderizzata al DOM. Invece, Vue mette in coda un aggiornamento DOM e quindi, su un timer, aggiorna il DOM. Normalmente, questo accade così velocemente che non fa differenza, ma, a volte, è necessario aggiornare il DOM renderizzato dopo che Vue lo ha renderizzato, cosa che non puoi fare immediatamente in un metodo perché l'aggiornamento non è avvenuto ancora. In quei casi, useresti nextTick. Documentato qui .
Bert

A complemento di quanto affermato da @Bert in https://stackoverflow.com/q/47634258/9979046 sopra, il nextTick () verrà utilizzato negli Unit Tests, quando è necessario verificare se un elemento esiste in DOM (HTML), ad esempio, se ottieni alcune informazioni su una richiesta Axios.
Oscar Alencar

Risposte:


139

nextTick ti consente di fare qualcosa dopo aver modificato i dati e VueJS ha aggiornato il DOM in base alla modifica dei dati, ma prima che il browser abbia visualizzato quelli modificati nella pagina.

Normalmente, gli sviluppatori utilizzano la funzione JavaScript nativa setTimeout per ottenere un comportamento simile. Tuttavia, l'utilizzo setTimeoutcede il controllo al browser prima che ti restituisca il controllo tramite la richiamata.

Diciamo che hai modificato alcuni dati. Vue aggiorna il DOM in base ai dati. Tenete presente che le modifiche al DOM non sono ancora state visualizzate sullo schermo dal browser. Se hai usato nextTick, la tua richiamata viene chiamata ora. Quindi, il browser aggiorna la pagina. Se lo usassi setTimeout, la tua richiamata verrebbe chiamata solo ora.

Puoi visualizzare questo comportamento creando un piccolo componente come il seguente:

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

Esegui il tuo server locale. Vedrai il messaggio Threevisualizzato.

Ora sostituisci il tuo this.$nextTickconsetTimeout

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

Ricarica il browser. Vedrai Two, prima di vedere Three.

Controlla questo violino per vederlo dal vivo

Questo perché, Vue ha aggiornato il DOM a Two, ha dato il controllo al browser. Browser visualizzato Two. Quindi, ho chiamato la tua richiamata. Vue ha aggiornato il DOM a Three. Che il browser ha visualizzato di nuovo.

Con nextTick. Vue ha aggiornato il DOM a Two. Ho chiamato la tua richiamata. Vue ha aggiornato il DOM a Three. Quindi ha dato il controllo al browser. E il browser visualizzato Three.

Spero fosse chiaro.

Per capire come Vue lo implementa, è necessario comprendere il concetto di Event Loop e microtask .

Una volta che questi concetti sono chiari (er), controlla il codice sorgente per nextTick .


4
Una cosa che non capisco è che quando dici "vue aggiorna i dati" ti riferisci all'aggiornamento fatto con ex: this.name = 'foo'o ti riferisci all'iniezione di elementi html nella pagina?
hidar

Non vedo da nessuna parte nella storia di questa domanda in cui dice "vue aggiorna i dati" ... Dice "Vue aggiorna DOM in base ai dati". Ciò significa che quando si impostano i dati tramite this.name = 'foo'vue si aggiorna il modello di oggetti del documento per riflettere le modifiche apportate ai dati in base al modello e alle funzioni configurate.
ADJenks

24

Il contenuto è stato tratto da By Adrià Fontcuberta

La documentazione di Vue dice:

Vue.nextTick ([callback, context])

Rimanda la richiamata da eseguire dopo il successivo ciclo di aggiornamento DOM. Usalo subito dopo aver modificato alcuni dati per attendere l'aggiornamento del DOM.

Hmm ..., se all'inizio sembra intimidatorio, non ti preoccupare cercherò di spiegarlo il più semplice possibile. Ma prima ci sono 2 cose che dovresti sapere:

  1. Il suo utilizzo è raro. Come una di quelle carte magiche d'argento. Ho scritto diverse Vueapp e una o due volte mi sono imbattuto in nextTick ().

  2. È più facile da capire una volta che hai visto alcuni casi d'uso reali. Dopo aver preso l'idea, la paura se ne andrà e avrai uno strumento utile sotto la cintura.

Allora proviamoci.

Capire $ nextTick

Siamo programmatori, no? Useremo il nostro amato approccio divide et impera per provare a tradurre la descrizione di .nextTick()poco a poco. Inizia con:

Rimanda la richiamata

Ok, ora sappiamo che accetta una richiamata. Quindi sembra così:

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

Grande. Questa richiamata è rimandata (così dicono i millenial ritardata) fino a ...

il prossimo ciclo di aggiornamento DOM.

Va bene. Sappiamo che Vue esegue gli aggiornamenti DOM in modo asincrono . È dotato di un modo per mantenere questi aggiornamenti "memorizzati" fino a quando non è necessario applicarli. Crea una coda di aggiornamenti e la scarica quando necessario. Quindi, il DOM viene "patchato" e aggiornato alla sua ultima versione.

Che cosa?

Lasciami riprovare: immagina che il tuo componente faccia qualcosa di veramente essenziale e intelligente come this.potatoAmount = 3.Vue non rieseguirà automaticamente il rendering del componente (e quindi del DOM). Metterà in coda la modifica richiesta. Quindi, nel successivo "segno di spunta" (come in un orologio), la coda viene scaricata e l'aggiornamento viene applicato. Tada!

Va bene! Quindi sappiamo che possiamo usare nextTick()per passare una funzione di callback che viene eseguita subito dopo che i dati sono stati impostati e il DOM è stato aggiornato.

Come ho detto prima ... non così spesso. L'approccio del "flusso di dati" che guida Vue, React e l'altro di Google, che non menzionerò, lo rende per la maggior parte del tempo non necessario. Tuttavia, a volte dobbiamo aspettare che alcuni elementi appaiano / scompaiano / vengano modificati nel DOM. Questo è quando nextTick torna utile.

Usalo subito dopo aver modificato alcuni dati per attendere l'aggiornamento del DOM.

Esattamente! Questa è l'ultima parte della definizione che i documenti di Vue ci hanno fornito. All'interno del nostro callback, il DOM è stato aggiornato in modo da poter interagire con la versione "più aggiornata" di esso.

Provalo

Ok ok. Guarda la console e vedrai che il valore dei nostri dati viene aggiornato solo all'interno del callback di 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 d'uso

Proviamo a definire qualche utile caso d'uso per nextTick.

Immagina di dover eseguire alcune azioni quando un componente è montato. MA! non solo il componente. È inoltre necessario attendere che tutti i suoi figli siano montati e disponibili nel DOM. Dannazione! Il nostro gancio montato non garantisce il rendering dell'intero albero dei componenti.

Se solo avessimo uno strumento per attendere il prossimo ciclo di aggiornamento DOM ...

Hahaa:

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

In poche parole

Quindi: nextTickè un modo comodo per eseguire una funzione dopo che i dati sono stati impostati e il DOM è stato aggiornato.

Devi aspettare il DOM, forse perché devi eseguire qualche trasformazione o devi aspettare che una libreria esterna carichi la sua roba? Quindi usa nextTick.

Alcune persone usano anche nextTick nei loro unit test per assicurarsi che i dati siano stati aggiornati. In questo modo, possono testare la "versione aggiornata" del componente.

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

Non preoccuparti. Entrambi sono (quasi) la stessa cosa. Vue.nextTick()si riferisce al metodo API globale, mentre vm.$nextTick()è un metodo di istanza. L'unica differenza è che vm.$nextTicknon accetta un contesto come secondo parametro. È sempre associato a this(noto anche come istanza stessa).

Un ultimo pezzo di freschezza

Si noti che nextTickrestituisce a Promise, quindi possiamo andare completamente d'accordo async/awaite migliorare l'esempio:

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

2
Basta aggiungere l'autore originale e il collegamento, nella parte superiore della "tua" spiegazione.
Renan Cidale

1
Che fantastica spiegazione! Grazie mille per il tuo tempo e impegno.
Muaath Alhaddad

16

Next Tick fondamentalmente ti consente di eseguire un po 'di codice, dopo che la vue ha ri-renderizzato il componente quando hai apportato alcune modifiche alla proprietà reattiva (dati).

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

Dalla documentazione di Vue.js:

Rimanda la richiamata da eseguire dopo il successivo ciclo di aggiornamento DOM. Usalo subito dopo aver modificato alcuni dati per attendere l'aggiornamento del DOM.

Per saperne di più, qui .


2
aggiornarlo come? questo è quello che non capisco. se aggiorno vm.msg allora il dom è già aggiornato perché c'è un nuovo testo "ciao" .. quindi come posso aggiornarlo di nuovo? puoi pubblicare un violino con un esempio pls? grazie
hidar

ok, modifico la risposta e cercherò di spiegarla ulteriormente.
Daksh Miglani

@hidar puoi usarlo in situazioni in cui devi fare più aggiornamenti, ma vuoi renderizzare esplicitamente l'un l'altro a diversi cicli dom
Daksh Miglani

Non è per consentirti di aggiornare il DOM di per sé, ma per fare qualsiasi cosa con esso (aggiornarlo, leggere informazioni da esso, ecc.) Dopo che è stato influenzato / modificato dalle modifiche apportate da Vue (perché hai cambiato un valore di proprietà reattiva , eccetera).
zenw0lf

Questo è stato un esempio per renderlo più semplice.
Daksh Miglani

7

Per rendere più esplicita la risposta di Pranshat sulla differenza tra l'uso di nextTick e setTimeout, ho biforcato il suo violino: qui

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

Puoi vedere nel violino che quando si usa setTimeOut, i dati iniziali lampeggiano molto brevemente una volta che il componente viene montato prima di adattare la modifica. Mentre, quando si utilizza nextTick, i dati vengono dirottati, modificati, prima del rendering nel browser. Quindi, il browser mostra i dati aggiornati senza nemmeno alcuna conoscenza del vecchio. Spero che cancelli i due concetti in un colpo solo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.