Насколько нам известно, роль ключа заключается в следующем.
Когда v-for проходит, используйте id, uuid и т.п. в качестве ключей для уникальной идентификации узлов, чтобы ускорить визуализацию виртуального DOM.
Для данных, которые отзывчивая система не отслеживает, используйте метку времени, сгенерированную +new Date(), в качестве ключа для ручного запуска повторного рендеринга.
Обычно можно увидеть одну и ту же сцену, но вторая сцена выглядит следующим образом:
Итак, какова релевантная точка знаний о ключевом значении?
Официальные точки знаний API
Каково обоснование двух приведенных выше сценариев использования?
Помимо ключей, есть ли другой способ принудительно обновить DOM?
использованная литература
Официальные точки знаний API
В Vue.js key — это одно из 6 специальных свойств key, ref, is, slot, slot-scope, scope.
Значение ключа может быть числом или строкой.
Ключ в основном используется в алгоритме виртуального DOM Vue в качестве подсказки для идентификации VNode при сравнении списка новых узлов и списка старых узлов.
Если вы не используете ключи, Vue будет использовать алгоритм, который сводит к минимуму перемещение элементов, и попытается как можно больше исправлять или повторно использовать элементы одного и того же типа в одном и том же месте.
Если используются ключи, Vue будет записывать элементы в соответствии с порядком ключей,Если элемент, у которого когда-то был ключ, больше не появляется, он будет удален или уничтожен напрямую.
Дети с одним и тем же родителем должны иметь уникальные ключи. Повторяющиеся ключи вызывают ошибки рендеринга.
Наиболее распространенное использование: v-for
<ul>
<li v-for="item in items" :key="item.id">...</li>
</ul>
Наиболее распространенное использование 2: Принудительная замена элемента или компонента
Запустить жизненный цикл компонента
триггерный переход
<transition>
<span :key="text">{{ text }}</span>
</transition>
Когда текст меняется,<span>будет заменен, но не исправлен, поэтому переход будет запущен.
Мое понимание:При изменении текста изменяется ключ диапазона, то есть диапазон, который когда-то имел старый ключ, больше не отображается.Когда текст с новым значением используется в качестве ключа, появляется диапазон с новым ключом, тогда старый диапазон ключей будет удален, старый переход также будет удален, новый диапазон ключей запустит рендеринг, а новый переход запустится.
Каково обоснование двух приведенных выше сценариев использования?
В сочетании со знанием официального API, теперь оглядываясь на сцену в начале статьи поднята.
Сценарий 1: V-FOR, использование ID, UUID в качестве ключа, уникальный идентификационный узел ускоряет рендеринг виртуального DOM.
Отвечать:
Если вы не используете ключи, Vue будет использовать алгоритм, который сводит к минимуму перемещение элементов, и попытается как можно больше исправлять или повторно использовать элементы одного и того же типа в одном и том же месте.
Если используются ключи, Vue будет записывать элементы в соответствии с порядком ключей,Если элемент, у которого когда-то был ключ, больше не появляется, он будет удален или уничтожен напрямую.
Сценарий 2. Для данных, которые не отслеживаются реагирующей системой, используйте отметку времени, сгенерированную +new Date(), в качестве ключа для ручного запуска повторного рендеринга.
Если используются ключи, Vue будет записывать элементы в соответствии с порядком ключей,Если элемент, у которого когда-то был ключ, больше не появляется, он будет удален или уничтожен напрямую.
После вызова метода обновления ключ div, содержащего span и complexComponent, меняется, то есть div, у которого когда-то был старый ключ, больше не появляется. с новым ключом. , тогда старый раздел ключей будет удален, старый диапазон и сложный компонент также будут удалены, новый раздел ключей вызовет рендеринг, новый диапазон,Визуализирует новый комплексный компонент с новыми родительскими объектами propObj и propArr.
думать:
Почему они называются propObj и propArr?
Визуализирует новый комплексный компонент с новыми родительскими объектами propObj и propArr.Почему смело?
Поскольку obj и arr в Vue.js не могут обнаруживать изменения данных, obj — это добавление и удаление атрибутов (причина в том, что сеттер не срабатывает для добавления и удаления, а наблюдатель не сообщает внешнему миру об обновлении), и arr — элемент в массиве Переназначить или изменить свойство length (причина в том, что метод изменения самого массива не используется, перехватчик цепочки прототипов массива не срабатывает, а наблюдатель не сообщает внешнему миру об обновлении) .
так! Назначая новый ключ, удаляя старый ключ div, визуализируя новый ключ div, propObj и propArr снова запускают жизненный цикл в компоненте complexComponent и выполняют повторный рендеринг. **В настоящее время js-переменные propObj и propArr родительского компонента фактически получили новые значения, но DOM не срабатывает или VNode перерисовывается. **Вам необходимо принудительно обновить, обновив ключ.Говоря о forceUpdate, вы можете принудительно обновить DOM вручную через $forceUpdate().
Помимо ключей, есть ли другой способ принудительно обновить DOM?
Сценарий: родительский компонент изменяет данные, переданные дочернему компоненту, и обновление данных массива не обновляется в соответствии с this.$set. что делать?
this.productImages.forEach((product) => {
if (product.productId in this.productsState) {
product.status = this.productsState[product.productId];
}
});
В чем причина того, что не выполняется повторный рендеринг без использования this.$set для назначения данных?Во Vue.js обнаружение изменений для Array реализовано путем перехвата прототипов. Он также перехватывает методы push, pop, shift, unshift, splice, sort, reverse, fill и copyWithin для изменения содержимого самого массива. а такжеproduct.status = this.productsState[product.productId];Ни один из прослушиваемых методов, которые изменяют сам массив, не запускается, поэтому повторной визуализации не происходит.
обновить ключ компонента
Метод $forceUpdate
обновить ключ компонента
1. Куда лучше добавить этот ключ?
Просто добавьте его в родительский элемент this.productImages.
Если это не связано с передачей данных, его также можно добавить непосредственно к элементу, который необходимо обновить.
2. Какое значение ключа используется?
Теперь это грубая отметка времени +new Date() в качестве значения ключа.
Вы также можете использовать значение двусторонней привязки в качестве значения ключа, чтобы убедиться, что старое и новое значения ключа различаются.
3. Каков принцип ключа?
Алгоритм виртуального DOM vue.js должен найти тот же vNode, что и новый vNode, из старого списка vNode при обновлении vNode.Если в этом процессе задан ключ атрибута, процесс будет намного быстрее.
Другие подробности см. выше.
Метод $forceUpdate
Этот метод можно вызвать только для родительского компонента, чтобы вручную уведомить экземпляр vue о повторной визуализации.
// $forceUpdate源码
Vue.prototype.$forceUpdate = function () {
const vm: Component = this
if (vm._watcher) {
vm._watcher.update()
}
}
// update源码
/**
* Subscriber interface.
* Will be called when a dependency changes.
*/
update () {
/* istanbul ignore else */
if (this.lazy) {
this.dirty = true
} else if (this.sync) {
this.run()
} else {
queueWatcher(this)
}
}
1. Анализ принципа возможности обновления $forceUpdate
product.status = this.productsState[product.productId];после,На самом деле dep изменился в это время., но отзывчивая реализация массива Vue.js — это способ перехвата метода цепочки прототипов, и это изменение не обнаруживается, поэтому оно не будет автоматически перерисовываться, и обновление не будет запущено. поэтому мыС помощью $forceUpdate вызывается метод update в наблюдателе, содержащем dep, для достижения повторного рендеринга..
2. Можно ли прослушивать события в дочерних компонентах, отправлять события из родительского компонента и обновлять только дочерние компоненты?
Не можем.
Поскольку dep является наблюдателем и dep родительского компонента, а не дочернего компонента, this.productImages родительского компонента не обнаруживается и не обновляется в режиме реального времени, а не проблема дочернего компонента.
Я с нетерпением жду возможности пообщаться с вами и вместе добиться прогресса. Приглашаем вас присоединиться к созданной мной технической дискуссионной группе, тесно связанной с фронтенд-разработкой: