Зачем использоватьkey
?
Motivation
When you use React, at a single point in time you can think of the render() function as creating a tree of React elements. On the next state or props update, that render() function will return a different tree of React elements. React then needs to figure out how to efficiently update the UI to match the most recent tree.
переводить: Когда вы используете React, вы можете разместитьrender()
Функция рассматривается как создание дерева элементов React. При следующем обновлении состояния или реквизитаrender()
Функция вернет другое дерево элементов React. Потом,React
Нужно выяснить, как эффективно обновить пользовательский интерфейс, чтобы он соответствовал последнему дереву.
Короче говоря, здесь возникают две проблемы сложности алгоритма:
- Два элемента разных типов будут давать разные деревья
- Разработчики могут использовать
key
чтобы указать, какие дочерние элементы могут оставаться стабильными при рендеринге
Как работает ключ?
в реакцииkey
свойство – это особое свойство, которое присутствуетне для разработчиковиспользуется (например, вы устанавливаете для компонентаkey
Не могу получить компонент после этогоkey
реквизит),но для самой реакции.
реагировать эксплойтkey
Для идентификации компонентов это опознавательный знак, точно так же, как наше удостоверение личности используется для идентификации человека. каждыйkey
Соответствует компоненту, то же самоеkey
react считает, что это один и тот же компонент, так что то же самое последующее действиеkey
Соответствующие компоненты не будут созданы.
this.state = {
users: [{id:1,name: '张三'}, {id:2, name: '李四'}, {id: 2, name: "王五"}],
....//省略
}
render()
return(
<div>
<h3>用户列表</h3>
{this.state.users.map(u => <div key={u.id}>{u.id}:{u.name}</div>)}
</div>
)
);
Приведенный выше код находится вdom
После рендеринга и монтирования в списке пользователей только два пользователя Чжан Сан и Ли Си Ван Ву не показал обработку, в основном потому чтоreact
согласно сkey
Считается, что Li Si и Wang Wu — это один и тот же компонент, из-за чего первый из них рендерится, а последующие — отбрасываются.
Значение ключа должно быть уникальным и стабильным
Таким образом, естьkey
После атрибута можно установить соответствующую связь с компонентом,react
согласно сkey
чтобы решить, следует ли уничтожить и воссоздать компонент или обновить компонент.
-
один и тот же ключ, если свойства компонента различаются, компоненты реагируют только на обновление соответствующих свойств; отсутствие изменений не обновляется.
-
key
Если значение отличается, реакция сначала уничтожает компонент (компонент с состояниемcomponentWillUnmount
будет выполняться), затем заново создайте компонент (компонент с отслеживанием состоянияconstructor
а такжеcomponentWillUnmount
будет казнен)
не закончено (Я просто скажу несколько слов), во время развития проекта,Наиболее распространенный сценарий использования атрибута ключа — это случай, когда подкомпоненты динамически создаются массивом, и к каждому подкомпоненту необходимо добавить уникальное значение атрибута ключа..
index
использование
В массиве списка используйтеkey
Чтобы идентифицировать массив при создании дочерних компонентов, моя обычная практика:
{this.state.data.map((v,idx) => <Item key={idx} v={v} />)}
// index 作为key方便快捷一步到位
<ul>
<li key="0">a <input type="text"/></li>
<li key="1">b <input type="text"/></li>
<li key="2">c <input type="text"/></li>
</ul>
но···
Если это связано с динамическими изменениями в массиве, такими как добавление элементов в массив, удаление элементов или изменение порядка и т. д.index
так какkey
приведет к отображению неверных данных.
{this.state.data.map((v,idx) => <Item key={idx} v={v} />)}
// 开始时:['a','b','c']=>
<ul>
<li key="0">a <input type="text"/></li>
<li key="1">b <input type="text"/></li>
<li key="2">c <input type="text"/></li>
</ul>
// 数组重排 -> ['c','b','a'] =>
<ul>
<li key="0">c <input type="text"/></li>
<li key="1">b <input type="text"/></li>
<li key="2">a <input type="text"/></li>
</ul>
В приведенном выше примере после переупорядочения массиваkey
Соответствующие экземпляры не уничтожаются, а обновляются заново. Берем конкретный процесс обновленияkey=0
элементы для иллюстрации после переупорядочения массива:
-
компонент ре
render
получить новый виртуальныйdom
; -
Новый и старый два виртуальных
dom
провестиdiff
, и старые и новыеkey=0
с компонент,react
Если рассматривается один и тот же компонент, возможно только обновление компонента; -
затем сравните его
children
, текстовое содержимое содержимого оказывается другим (на a--->c), иinput
Компонент не изменился, затем активируйте компонентcomponentWillReceiveProps
метод, тем самым обновляя текстовое содержимое своих дочерних компонентов; -
потому что компонент
children
серединаinput
Компонент не изменился, и он такой же, как любой переданный в родительском компоненте.props
не связаны, так чтоinput
компоненты не будут обновляться (т.е. ихcomponentWillReceiveProps
метод не будет выполнен), что не приведет к изменению значения, введенного пользователем.
Этоindex
так какkey
существующие проблемы,index
так какkey
является анти-шаблоном,Не используйте индекс в качестве ключа легкомысленно. (Рекомендуется, если содержимое массива предназначено только для чистого отображения и не требует динамических изменений в массиве.)
Две демоверсии на официальном сайте:demo1, demo2, вы можете пойти и посмотреть.
index
заменять
В конечном итоге, используяindex
Проблема выполняет дваждыindex
то же самое, что приводит кkey
То же самое, вернемся к резюме выше 👆:Ключ тот же, если свойства компонента меняются, реакция только обновит свойства, соответствующие компонентам, если нет изменений, он не будет обновляться..
В это время, если гарантируется, что каждыйkey
Другое, разве проблема не решена?
Всегда ???
key={index + Math.random()}
Генерируется волшебная строка кода.
Может ли это решить проблему? могу! Это оптимально? нет.
просматриватьофициальная документация, что четко указано в официальной документацииDon’t pass something like Math.random() to keys
.
Ключи должны быть стабильными, предсказуемыми и уникальными. нестабильныйkey
(например, ключ, сгенерированныйMath.random()
) приведет к ненужному воссозданию многих экземпляров компонентов и узлов DOM, что может привести к снижению производительности и потере состояния в дочерних компонентах.
Поэтому, когда вы не можете использоватьrandom
Генерируется случайным образомkey
, мы можем использовать глобальныйlocalCounter
переменная для добавления стабильного уникальногоkey
стоимость.
var localCounter = 1;
this.data.forEach(el=>{
el.id = localCounter++;
});
//向数组中动态添加元素时,
function createUser(user) {
return {
...user,
id: localCounter++
}
}
Итак, мое окончательное решение состояло в том, чтобы определить переменную глобально:let ONE = 1;
, то в компоненте используйтеkey = {ONE++}
. такsetSete()
каждый разkey
изменились и в какой-то степени избежалиkey
неустойчивый характер. Проблема решена, заткнись.
Добавить проблему сценария:
Проблема, с которой столкнулись в то время, заключалась в следующем: нужно изменить свойства внутренних компонентов, а
key
Установите над внешним подкомпонентом. первое использованиеindex
так какkey
, Индекс внешнего подкомпонента одинаков для двух рендеров, поэтому реакция находит внешний подкомпонент и распознает его.key = index
, Обнаружитьkey
без изменений.key
То же, если свойства компонента меняются, тоreact
Обновляются только свойства, соответствующие компоненту, изменения не вносятся. На самом деле во внешнем подкомпоненте нет изменения свойства, а измененное свойство находится во внутреннем компоненте. такreact
Он завершается, когда найден внешний подкомпонент. Внутренний подкомпонент эквивалентен тому, что все еще не отображается.