Примечания: React в кратком изложении ключа

внешний интерфейс алгоритм React.js

Зачем использовать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Соответствует компоненту, то же самоеkeyreact считает, что это один и тот же компонент, так что то же самое последующее действиеkeyСоответствующие компоненты не будут созданы.

Markdown

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будет казнен)

Markdown

не закончено (Я просто скажу несколько слов), во время развития проекта,Наиболее распространенный сценарий использования атрибута ключа — это случай, когда подкомпоненты динамически создаются массивом, и к каждому подкомпоненту необходимо добавить уникальное значение атрибута ключа..

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является анти-шаблоном,Не используйте индекс в качестве ключа легкомысленно. (Рекомендуется, если содержимое массива предназначено только для чистого отображения и не требует динамических изменений в массиве.)

Markdown

Две демоверсии на официальном сайте:demo1, demo2, вы можете пойти и посмотреть.

indexзаменять

В конечном итоге, используяindexПроблема выполняет дваждыindexто же самое, что приводит кkeyТо же самое, вернемся к резюме выше 👆:Ключ тот же, если свойства компонента меняются, реакция только обновит свойства, соответствующие компонентам, если нет изменений, он не будет обновляться..

В это время, если гарантируется, что каждыйkeyДругое, разве проблема не решена?

Всегда ???

key={index +  Math.random()}

Генерируется волшебная строка кода.

Может ли это решить проблему? могу! Это оптимально? нет.

Markdown

просматриватьофициальная документация, что четко указано в официальной документации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неустойчивый характер. Проблема решена, заткнись.

Markdown

Добавить проблему сценария:

Проблема, с которой столкнулись в то время, заключалась в следующем: нужно изменить свойства внутренних компонентов, аkeyУстановите над внешним подкомпонентом. первое использованиеindexтак какkey, Индекс внешнего подкомпонента одинаков для двух рендеров, поэтому реакция находит внешний подкомпонент и распознает его.key = index, Обнаружитьkeyбез изменений.keyТо же, если свойства компонента меняются, тоreactОбновляются только свойства, соответствующие компоненту, изменения не вносятся. На самом деле во внешнем подкомпоненте нет изменения свойства, а измененное свойство находится во внутреннем компоненте. такreactОн завершается, когда найден внешний подкомпонент. Внутренний подкомпонент эквивалентен тому, что все еще не отображается.

Ссылаться на:

Подробное объяснение ключа React

Ключ документации React на китайском языке

Ключ документации React на китайском языке