Co jest następneTick lub co robi w VueJs

117

Czytałem dokumenty, ale nie mogę tego zrozumieć. Wiem, jakie dane, obliczone, obserwowane, metody robią, ale do czego nextTick()służą vuejs?

hidar
źródło
20
Kluczową koncepcją, którą należy zrozumieć, jest to, że DOM jest aktualizowany asynchronicznie . Kiedy zmieniasz wartość w Vue, zmiana nie jest natychmiast renderowana w DOM. Zamiast tego Vue kolejkuje aktualizację DOM, a następnie aktualizuje DOM według timera. Zwykle dzieje się to tak szybko, że nie robi różnicy, ale czasami trzeba zaktualizować wyrenderowany DOM po wyrenderowaniu go przez Vue, czego nie można od razu zrobić w metodzie, ponieważ aktualizacja nie nastąpiła jeszcze. W takich przypadkach użyjesz nextTick. Udokumentowane tutaj .
Bert
Uzupełniając to, co powiedział @Bert w https://stackoverflow.com/q/47634258/9979046 powyżej, metoda nextTick () zostanie użyta w testach jednostkowych, gdy trzeba sprawdzić, czy element istnieje w DOM (HTML), na przykład, jeśli otrzymasz informacje na temat wniosku Axios.
Oscar Alencar
dlaczego mam wrażenie, że nextTick jest czymś w rodzaju const nextTick = (callback, context) => { setTimeout(callback.bind(context), 0); };?
SparK

Odpowiedzi:

152

nextTick pozwala ci coś zrobić po zmianie danych i zaktualizowaniu przez VueJS DOM na podstawie zmian twoich danych, ale zanim przeglądarka wyrenderuje te zmiany na stronie.

Zwykle programiści używają natywnej funkcji JavaScript setTimeout, aby osiągnąć podobne zachowanie. Jednak użycie setTimeoutpowoduje zrzeczenie się kontroli nad przeglądarką, zanim przekaże ją z powrotem za pośrednictwem wywołania zwrotnego.

Powiedzmy, że zmieniłeś niektóre dane. Vue aktualizuje DOM na podstawie danych. Pamiętaj, że zmiany DOM nie są jeszcze renderowane na ekranie przez przeglądarkę. Jeśli użyłeś nextTick, oddzwonimy teraz. Następnie przeglądarka aktualizuje stronę. Jeśli użyjesz setTimeout, oddzwonienie zostanie wywołane dopiero teraz.

Możesz zwizualizować to zachowanie, tworząc mały komponent, taki jak następujący:

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

Uruchom serwer lokalny. Zobaczysz wyświetlany komunikat Three.

Teraz wymienić this.$nextTickzsetTimeout

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

Załaduj ponownie przeglądarkę. Zobaczysz Two, zanim zobaczysz Three.

Sprawdź to skrzypce, aby zobaczyć to na żywo

Dzieje się tak, ponieważ Vue zaktualizował DOM do Two, przekazując kontrolę przeglądarce. Wyświetlana przeglądarka Two. Następnie zadzwoniłem do twojego oddzwonienia. Vue zaktualizowało DOM do Three. Która przeglądarka wyświetliła się ponownie.

Z nextTick. Vue zmienił DOM na Two. Zadzwoniłem do twojego oddzwonienia. Vue zaktualizowało DOM do Three. Następnie przekazał kontrolę przeglądarce. I wyświetlona przeglądarka Three.

Mam nadzieję, że to było jasne.

Aby zrozumieć, jak Vue to implementuje, musisz zrozumieć koncepcję pętli zdarzeń i mikrozadań .

Gdy już zrozumiesz te koncepcje, sprawdź kod źródłowy dla nextTick .

Prashant
źródło
4
Jedna rzecz, której nie rozumiem, to kiedy mówisz „vue aktualizuje dane”, odnosisz się do zaktualizowanej wersji, np. this.name = 'foo'Czy odnosisz się do wstawienia elementów html na stronę?
hidar
Nie widzę w historii tego pytania gdzie on mówi „vue aktualizuje dane”… Mówi „Vue aktualizuje DOM na podstawie danych”. Oznacza to, że kiedy ustawiasz dane przez this.name = 'foo'vue, aktualizuje model obiektu dokumentu, aby odzwierciedlić zmiany wprowadzone w danych w oparciu o szablon i funkcje, które konfigurujesz.
ADJenks
27

Treść pochodzi z By Adrià Fontcuberta

Dokumentacja Vue mówi:

Vue.nextTick ([wywołanie zwrotne, kontekst])

Odroczenie wywołania zwrotnego po następnym cyklu aktualizacji DOM. Użyj go natychmiast po zmianie niektórych danych, aby poczekać na aktualizację DOM.

Hmm ... jeśli na początku wydaje się on onieśmielający, nie martw się, postaram się to wyjaśnić tak prosto, jak to tylko możliwe. Ale najpierw są dwie rzeczy, o których powinieneś wiedzieć:

  1. Jego użycie jest rzadkie. Jak jedna z tych srebrnych magicznych kart. Napisałem kilka Vueaplikacji i raz lub dwa wpadłem na nextTick ().

  2. Łatwiej jest to zrozumieć, gdy zobaczysz prawdziwe przypadki użycia. Gdy wpadniesz na pomysł, strach minie, a będziesz miał pod paskiem przydatne narzędzie.

W takim razie zróbmy to.

Zrozumienie $ nextTick

Jesteśmy programistami, prawda? Skorzystamy z naszego ukochanego podejścia dziel i podbijaj, aby spróbować przetłumaczyć opis .nextTick()po kawałku. Zaczyna się od:

Odłóż oddzwonienie

Ok, teraz wiemy, że akceptuje oddzwonienie. Więc wygląda to tak:

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

Świetny. To oddzwonienie jest odroczone (tak mówią milenialsi) do…

następny cykl aktualizacji DOM.

W porządku. Wiemy, że Vue wykonuje aktualizacje DOM asynchronicznie . Zawiera sposób na przechowywanie tych aktualizacji do czasu ich zastosowania. Tworzy kolejkę aktualizacji i opróżnia ją w razie potrzeby. Następnie DOM jest „łatany” i aktualizowany do najnowszej wersji.

Co?

Spróbuję jeszcze raz: wyobraź sobie, że twój komponent robi coś naprawdę istotnego i inteligentnego, na przykład this.potatoAmount = 3.Vue nie wyrenderuje komponentu (a tym samym DOM) automatycznie. Ustawi w kolejce wymaganą modyfikację. Następnie w następnym „tyknięciu” (jak w zegarze) kolejka jest opróżniana, a aktualizacja jest stosowana. Tada!

W porządku! Wiemy więc, że możemy użyć nextTick()do przekazania funkcji zwrotnej, która jest wykonywana zaraz po ustawieniu danych i zaktualizowaniu DOM.

Jak powiedziałem wcześniej… nie tak często. Podejście „przepływu danych”, które napędza Vue, React i inne rozwiązanie od Google, o którym nie wspomnę, sprawia, że ​​przez większość czasu jest to niepotrzebne. Jednak czasami musimy poczekać, aż niektóre elementy pojawią się / znikną / zostaną zmodyfikowane w DOM. Wtedy przydaje się nextTick.

Użyj go natychmiast po zmianie niektórych danych, aby poczekać na aktualizację DOM.

Dokładnie! To ostatnia definicja, którą dostarczyła nam dokumentacja Vue. Wewnątrz naszego wywołania zwrotnego DOM został zaktualizowany, abyśmy mogli wchodzić w interakcje z „najbardziej zaktualizowaną” jego wersją.

Udowodnij to

Dobrze, dobrze. Zobacz konsolę, a zobaczysz, że wartość naszych danych jest aktualizowana tylko w wywołaniu zwrotnym 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>

Przypadek użycia

Spróbujmy zdefiniować kilka przydatnych przypadków użycia nextTick.

Wyobraź sobie, że musisz wykonać jakąś czynność po zamontowaniu komponentu. ALE! nie tylko komponent. Musisz także poczekać, aż wszystkie jego elementy podrzędne zostaną zamontowane i dostępne w DOM. Cholera! Nasz zamontowany hak nie gwarantuje renderowania całego drzewa komponentów.

Gdybyśmy tylko mieli narzędzie do czekania na kolejny cykl aktualizacji DOM…

Hahaa:

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

W skrócie

A więc: nextTickto wygodny sposób na wykonanie funkcji po ustawieniu danych i zaktualizowaniu modelu DOM.

Musisz poczekać na DOM, może dlatego, że musisz wykonać jakąś transformację lub musisz poczekać, aż zewnętrzna biblioteka załaduje swoje rzeczy? Następnie użyj nextTick.

Niektórzy ludzie używają również nextTick w swoich testach jednostkowych, aby upewnić się, że dane zostały zaktualizowane. W ten sposób mogą przetestować „zaktualizowaną wersję” komponentu.

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

Nie martw się. Obie są (prawie) takie same. Vue.nextTick()odnosi się do globalnej metody API, a vm.$nextTick()jest metodą instancji. Jedyna różnica polega na tym, vm.$nextTickże nie akceptuje kontekstu jako drugiego parametru. Zawsze jest do tego przypisana this(nazywana również samą instancją).

Ostatni kawałek chłodu

Zwróć uwagę, że nextTickzwraca a Promise, więc możemy przejść do końca async/awaiti ulepszyć przykład:

async mounted () {
    this.message = 'updated'
    console.log(this.$el.textContent) // 'not updated'
    await this.$nextTick()
    console.log(this.$el.textContent) // 'updated'
}
Humoyun Ahmad
źródło
4
Po prostu dodaj oryginalnego autora i link u góry „Twojego” wyjaśnienia.
Renan Cidale
1
Co za niesamowite wyjaśnienie! Dziękuję bardzo za poświęcony czas i wysiłek.
Muaath Alhaddad
Cholera, właśnie skopiowałeś cały post z medium. Głosowano w dół.
Alexander Kim
Kiedy programiści szukają odpowiedzi w Google, StackOverflowwyniki są zwykle pierwsze, SO jest de facto miejscem, w którym można znaleźć odpowiedzi, ale istnieje wiele dobrych zasobów w Internecie, które mogą nie pojawiać się w wynikach wyszukiwania. Więc spędziłem prawie pół godziny na tę odpowiedź, to nie jest tylko kopiowanie, jak powiedziałeś, autorowi przypisywano od początku. Jeśli nie podoba ci się ten post, jest OK. Ale powinieneś szanować pracę innych
Humoyun Ahmad
16

Next Tick w zasadzie pozwala na uruchomienie jakiegoś kodu po tym, jak vue ponownie wyrenderuje komponent, gdy dokonałeś pewnych zmian we właściwości reaktywnej (danych).

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

Z dokumentacji Vue.js:

Odroczenie wywołania zwrotnego po następnym cyklu aktualizacji DOM. Użyj go natychmiast po zmianie niektórych danych, aby poczekać na aktualizację DOM.

Przeczytaj więcej na ten temat tutaj .

Daksh Miglani
źródło
2
zaktualizować jak? tego nie rozumiem. jeśli zaktualizuję vm.msg, to dom jest już zaktualizowany, ponieważ jest nowy tekst „witaj” .. więc jak mogę go ponownie zaktualizować? czy możesz
wysłać
ok, poprawię odpowiedź i spróbuję to dokładniej wyjaśnić.
Daksh Miglani
@hidar możesz go używać w sytuacjach, gdy musisz wykonać wiele aktualizacji, ale chcesz jawnie renderować się nawzajem w różnych cyklach dom
Daksh Miglani,
Nie chodzi o to, abyś mógł aktualizować DOM jako taki, ale robić cokolwiek z nim (czy to aktualizować, czytać informacje z niego, itp.) Po zmianie / modyfikacji przez zmiany dokonane przez Vue (ponieważ zmieniłeś reaktywną wartość właściwości itp.).
zenw0lf
To był przykład, aby to uprościć.
Daksh Miglani
7

Aby uściślić odpowiedź Pranshata na temat różnicy między używaniem nextTick i setTimeout, bardziej precyzyjnie, rozwidliłem jego skrzypce: tutaj

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

Możesz zobaczyć na skrzypcach, że podczas używania setTimeOut początkowe dane migają bardzo krótko po zamontowaniu komponentu przed dostosowaniem zmiany. Podczas gdy podczas korzystania z nextTick dane są przechwytywane, zmieniane przed renderowaniem do przeglądarki. Tak więc przeglądarka wyświetla zaktualizowane dane nawet bez znajomości starych. Mam nadzieję, że to wyjaśnia te dwie koncepcje za jednym zamachem.

Pręga po uderzeniu biczem
źródło