nextTick
официальное объяснение- Отложить обратный вызов до завершения следующего цикла обновления DOM. Используйте его сразу после изменения данных, а затем дождитесь обновления DOM.
Мое понимание - асинхронное выполнение, вызываемое в начале следующего цикла событий
Макро или микро?
Не рассматривая совместимость, спросите конкретную реализацию nextTick?
На основе исходного кода разных периодов будут разные ответы.
Что такое макрозадачи/микрозадачи?
| задача макроса | микрозадачи |
|---|---|
| setTimeout | process.nextTick |
| setInterval | MutationObserver |
| setImmediate | Promise.then |
| requestAnimationFrame | |
| MessageChannel |
повторять
Фактически, nextTick несколько раз корректировался для различных проблем с рендерингом и событиями dom в разных версиях разработки vue. Макро/микрозадачи или даже и то, и другое параллельно. Стабильно в последней версии 2.6.12 какмикрозадачи. Чтобы изучить конкретные причины и проблемы, с которыми я столкнулся, я просмотрел несколько версий исходного кода, чтобы найти ответ.
v2.0.0 - v2.4.4 Микрозадачи
Изначально, начиная с vue2.0, он основывался наMutationObserverилиPromiseОбработанные микрозадачи
Содержание комментариев ниже касается того, что MutationObserver имеет странную ошибку задержки в веб-просмотре на ios >= 9.3.3, поэтому Promise предпочтительнее.
Последующие рисунки — это скриншоты исходного кода Vue, а путь указан в первой строке рисунка.
возникающие проблемы
Приоритет микрозадач слишком высок, из-за чего обработка рендеринга Vue оказывается зажатой между всплытием событий или несколькими последовательными событиями.
Здесь я использую классический#6566чтобы объяснить проблему.
<div v-if="show">
<i @click="show = false">show is true</i>
</div>
<div v-else @click="show = true">
<i>show is false</i>
</div>
На самом деле, после того, как вы нажмете на текст тега i, вы всегда увидитеshow is true. Поскольку два элемента DOM, управляемые v-if, имеют одинаковую структуру, vue повторно использует элементы, а также отвязывает и связывает события их родителя и дочернего элемента. Поскольку приоритет микрозадачи слишком высок, когда событие всплывает на div, оно уже привязано@click="show = true", что приводит к обратному изменению состояния. Таким образом, вы можете видеть толькоshow is true.
v2.5.0 - макро-задачи v2.5.1
Для того, чтобы решить вышеуказанные проблемы, в этой версии полностью изменена задача макроса. Предпочтительно использовать setImmediate и MessageChannel. Даже если для setTimeout установлено значение setTimeout(fn, 0), по стандарту будет минимальная задержка, обычно 4 мс. А setImmediate и MessageChannel сразу вставляются в задачу макроса.
возникающие проблемы
Задача макроса снова выполняется слишком медленно, что приводит к слишком медленному рендерингу анимации и переходов между состояниями страницы.
#6813Есть список, css контрол отображается вертикально при ширине экрана 1000px, и при этомv-showКонтролируйте скрытие списка при изменении ширины страницы монитора на 1000 пикселей. Из-за использования макросов, несмотря на то, что состояние v-show было установлено как false, перекомпоновка, вызванная перерисовкой vue dom, и перекомпоновка, вызванная css, не находятся в одном и том же цикле событий и будут позже. Таким образом, страница будет иметь два эффекта перекомпоновки, в которых список отображается вертикально, а затем скрывается, вызывая мерцание экрана.
v2.5.2 - v2.5.20 Микро-макропараллелизм
Поэтому здесь принята параллельная стратегия микрозадачи + макрозадачи.По умолчанию используются микрозадачи, и только макрозадачи используются, когда выполняется связанная функция события.
Как показано на рисунке, witchMacroTask вызывается, когда событие связано, поэтому функция события выполняет макрозадачу.
вызвать проблемы
Однако проблема повторилась.Неразрешимые проблемы, вызванные макрозадачей event all-going, если интересно, то можно посмотреть подробнее. Личное понимание в основном вызвано мерами защиты конфиденциальности пользователей в системе ios, надеюсь кто-то сможет дать развернутый ответ.
v2.6.0 - v2.6.12 Микрозадачи
В конце концов он вернулся к микрозадачам, но внес некоторые изменения в выполнение событий. Предотвратить выполнение функции из-за слишком высокого приоритета микрозадач в некоторых случаях, обнаруженных раньше.