Що таке nextTick або що він робить у VueJs


104

Я читаю документи, але не можу це зрозуміти. Я знаю, що роблять дані, обчислені, дивляться, методи, але для чого nextTick()використовують vuejs?


17
Ключова концепція, яку потрібно зрозуміти, - це те, що DOM оновлюється асинхронно . Коли ви змінюєте значення у Vue, зміна не надається негайно DOM. Натомість Vue чергає на оновлення DOM, а потім на таймері оновлює DOM. Зазвичай це відбувається настільки швидко, що це не має значення, але, часом, вам потрібно оновити відредагований DOM після того, як Vue його зробив, чого не можна відразу зробити в методі, оскільки оновлення не відбулося поки що. У цих випадках ви б використовували nextTick. Задокументовано тут .
Берт

Доповнюючи те, що @Bert сказав у https://stackoverflow.com/q/47634258/9979046 вище, nextTick () буде використовуватися в Unit Tests, коли потрібно перевірити, чи існує елемент у DOM (HTML), наприклад, якщо ви отримаєте якусь інформацію на запит Axios.
Оскар Аленкар

Відповіді:


139

nextTick дозволяє вам щось робити після того, як ви змінили дані, і VueJS оновив DOM на основі зміни ваших даних, але перед тим, як веб-переглядач зробив зміни, змінені на сторінці.

Зазвичай розробники використовують вбудовану функцію JavaScript setTimeout для досягнення подібної поведінки. Але, використовуючи, setTimeoutвідмовляється від контролю над браузером, перш ніж він поверне вам контроль за допомогою зворотного дзвінка.

Скажімо, ви змінили деякі дані. Vue оновлює DOM на основі даних. Зверніть увагу, що зміни DOM ще не відображаються на екрані браузером. Якщо ви раніше використовували nextTick, ваш зворотний дзвінок буде дзвонено зараз. Потім браузер оновлює сторінку. Якщо ви використовували setTimeout, ваш зворотний дзвінок буде дзвонити лише зараз.

Ви можете візуалізувати цю поведінку, створивши невеликий компонент на зразок наступного:

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

Запустіть свій локальний сервер. Ви побачите повідомленняThree яке відображається.

Тепер замініть this.$nextTickнаsetTimeout

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

Перезавантажте браузер. Ви побачите Two, перш ніж побачитеThree .

Перевірте цю скрипку, щоб побачити її в прямому ефірі

Це тому, що Vue оновив DOM до Two, дав контроль браузеру. Відображається браузер Two. Потім зателефонував зворотний дзвінок. Vue оновив DOM до Three. Який браузер відобразився знову.

З nextTick. Vue udpated DOM до Two. Викликали зворотний дзвінок. Vue оновив DOM доThree . Потім передав контроль браузеру. І браузер відображається Three.

Сподіваюся, це було зрозуміло.

Щоб зрозуміти, як Vue реалізує це, вам потрібно зрозуміти концепцію циклу подій та мікрозадачі .

Після того, як ви зрозумієте ці поняття (er), перевірте вихідний код на nextTick .


4
Я не розумію однієї речі, коли ви говорите: "Vue оновлює дані", ви посилаєтесь на оновлені зроблені з ex: this.name = 'foo'або ви переглядаєте введення елементів html на сторінку?
hidar

Я не бачу ніде в історії цього питання, де він говорить "vue оновлює дані" ... Він каже "Vue оновлює DOM на основі даних". Що означає, що при встановленні даних через this.name = 'foo'vue оновляється модель об'єкта документа для відображення змін, внесених до даних на основі шаблону та функцій, які ви налаштовуєте.
ADJenks

24

Зміст було взято з За Адріа Fontcuberta

Документація Vue говорить:

Vue.nextTick ([зворотний дзвінок, контекст])

Відкладіть зворотний виклик, який буде виконаний після наступного циклу оновлення DOM. Використовуйте його відразу після зміни деяких даних, щоб дочекатися оновлення DOM.

Хм ..., якщо спочатку це залякає, не хвилюйся, я спробую пояснити це якомога простіше. Але спершу слід знати дві речі:

  1. Його використання є рідкістю. Як одна з цих срібних магічних карток. Я написав кілька Vueдодатків і наткнувся на nextTick () один або два рази.

  2. Це легше зрозуміти, побачивши реальні випадки використання. Після того, як ви отримаєте ідею, страх згасне, і у вас буде зручний інструмент під поясом.

Давай підемо за цим.

Розуміння $ nextTick

Ми програмісти, чи не так? Ми використаємо наш улюблений поділ і підкоримо підхід, щоб спробувати перекласти опис .nextTick()поступово. Починається з:

Відкладіть зворотний дзвінок

Гаразд, тепер ми знаємо, що він приймає зворотний дзвінок. Так це виглядає приблизно так:

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

Чудово. Цей зворотний виклик відкладається (ось, як кажуть затримки тисячоліття) до…

наступний цикл оновлення DOM

Добре. Ми знаємо, що Vue виконує оновлення DOM асинхронно . У ньому є спосіб зберігання цих оновлень «зберігатися», поки не потрібно їх застосувати. Він створює чергу оновлень і стирає її при необхідності. Потім DOM "виправлено" та оновлено до останньої версії.

Що?

Дозвольте спробувати ще раз: Уявіть, що ваш компонент робить щось дійсно важливе та розумне, як this.potatoAmount = 3.Vue, не буде рендерировать компонент (і, таким чином, DOM) автоматично. Він буде в черзі до потрібної модифікації. Потім, у наступному "галочці" (як у годиннику), черга змивається і застосовується оновлення. Тада!

Добре! Тож ми знаємо, що можемо використовувати nextTick()для передачі функції зворотного дзвінка, яка виконується відразу після встановлення даних та оновлення DOM.

Як я вже говорив раніше ... не так часто. Підхід "потік даних", який запускає Vue, React та інший від Google, про який я не згадую, робить його непотрібним більшу частину часу. Однак іноді нам потрібно почекати, поки деякі елементи з’являться / зникають / змінюються в DOM. Це коли корисний nextTick.

Використовуйте його відразу після зміни деяких даних, щоб дочекатися оновлення DOM.

Саме так! Це остання частина визначення, яку нам надали документи Vue. Всередині нашого зворотного дзвінка DOM оновлено, тому ми можемо взаємодіяти з його „найновішою” версією.

Докажи це

Добре-добре. Подивіться на консоль, і ви побачите, що значення наших даних оновлюється лише всередині зворотного виклику 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>

Випадок використання

Спробуємо визначити якийсь корисний варіант використання nextTick .

Уявіть, що вам потрібно виконати певну дію, коли компонент змонтовано. АЛЕ! не тільки компонент. Вам також потрібно почекати, поки всі його дочірні елементи будуть змонтовані та доступні в DOM. Чорт! Наш змонтований гачок не гарантує, що дерево всього компонента буде представлене.

Якби тільки ми мали інструмент, щоб дочекатися наступного циклу оновлення DOM ...

Хахаа:

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

Коротко

Отже: nextTickце зручний спосіб виконати функцію після встановлення даних та оновлення DOM.

Вам потрібно почекати DOM, можливо, тому, що вам потрібно виконати певне перетворення, або вам потрібно почекати, поки зовнішня бібліотека завантажить її матеріали? Потім використовуйте nextTick.

Деякі люди також використовують nextTick у своїх одиничних тестах як спосіб забезпечити оновлення даних. Таким чином, вони можуть протестувати "оновлену версію" компонента.

Vue.nextTick () або vm. $ NextTick ()?

Не хвилюйся. Обидва (майже) однакові. Vue.nextTick()відноситься до глобального методу API, тоді vm.$nextTick()як метод екземпляра. Єдина відмінність полягає в тому, vm.$nextTickщо не приймає контекст як другий параметр. Він завжди пов'язаний this(також відомий як сам екземпляр).

Останній шматочок прохолоди

Зауважте, що nextTickповертається "a" Promise, тому ми можемо перейти в повний клас async/awaitі покращити приклад:

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

2
Просто додайте оригіналу автора та посилання вгорі "вашого" пояснення.
Ренан Сідал

1
Яке дивовижне пояснення! Дуже дякую за ваш час та зусилля.
Муаат Алхаддад

16

Next Tick в основному дозволяє запустити деякий код після того, як vue повторно надав компонент, коли ви внесли деякі зміни в реактивну властивість (дані).

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

З документації Vue.js:

Відкладіть зворотний дзвінок після виконання наступного циклу оновлення DOM. Використовуйте його відразу після зміни деяких даних, щоб дочекатися оновлення DOM.

Детальніше про це читайте тут .


2
оновити як? це те, чого я не беруся. якщо я оновлю vm.msg, тоді dom вже оновлено, тому що з'явився новий текст '' привіт '' .. так як я можу оновити його знову? Ви можете опублікувати скрипку з прикладом pls? спасибі
hidar

добре, я відредагую відповідь і спробую пояснити її далі.
Дакш Міглані

@hidar ви можете використовувати його в ситуаціях, коли вам доведеться робити кілька оновлень, але ви хочете чітко відображати один одного на різних циклах дому
Daksh Miglani

Це не для того, щоб дозволити вам оновлювати DOM як таку, а робити що-небудь з ним (будь то оновлення, читати інформацію з нього тощо) після того, як це було вплинуто / модифіковано змінами, зробленими Vue (оскільки ви змінили значення реактивного властивості тощо).
zenw0lf

Це був приклад для спрощення.
Дакш Міглані

7

Щоб зробити відповідь Праншета про різницю між використанням nextTick і setTimeout, явнішою, я роздрібнив його загадку: тут

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

Ви можете бачити, що при використанні setTimeOut початкові дані блимають дуже коротко, коли компонент встановлюється перед адаптацією зміни. В той час, коли при використанні nextTick дані викрадаються, змінюються, перш ніж відображатись у браузері. Отже, браузер показує оновлені дані, навіть не знаючи старих. Сподіваюсь, що одним махом очищає два поняття.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.