предисловие
Источник темы:nuggets.capable/post/684490…
Цель: Расширить и углубить свои знания с помощью вопросов на собеседовании.
(Диди, голодный) Зачем нужно писать ключ в компоненте списка при написании проекта React/Vue, и какова его роль?
Какое ключевое слово
Сначала мы начинаем сОфициальный сайтОбъяснение начинается словами:
фокус
- Ключ будет использоваться в алгоритме виртуального DOM (алгоритме сравнения) для различения старых и новых узлов.
- При отсутствии ключа смена элементов будет сведена к минимуму, а одни и те же элементы будут использоваться максимально. (повторное использование на месте)
- Когда это с ключом, он будет организован на основе того же ключа. (такое же мультиплексирование)
- С ключом он также может запускать эффекты перехода и запускать жизненный цикл компонентов.
Вышеуказанные 4 пункта являются основными пояснениями в официальном документе. Прочитав вышеперечисленные пункты, вы узнаете, что такое ключ и его функции.
Подсмотреть роль ключа в алгоритме diff с уровня исходного кода
- При оценке того, является ли это одним и тем же узлом
Мы знаем, что алгоритм diff определит, являются ли четыре узла в начале и в конце одним и тем же узлом, и первый шаг этого же Vnode — определить ключевое значение двух элементов.Это означает, что ключ один и тот же, они могут быть одним и тем же элементом, а не одним и тем же, напрямую возвращать false.
- При оценке того, является ли это одним и тем же статическим узлом
- При создании карты ключевых индексов
Здесь я просто перехватил фрагмент кода.Этот шаг заключается в генерации карты ключ-индекс из массива подэлементов vnode, чтобы было удобно через ключ находить соответствующий подэлемент индекса и сравнивать одинаковые узлы. Вышеупомянутый случай, когда сравнение между передними и задними 4 новыми и старыми узлами не увенчалось успехом, следующее - найти тот же элемент через эту карту.
С ключом или без ключа, кто быстрее
Говоря о теме скорости, мы можем сначала сравнить по существу.
Давайте рассмотрим простой пример рендеринга данных.
- Не брать ключ
Код экземпляра выглядит следующим образом:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<div @click="changeData">切换数据</div>
<li v-for="item in list">{{ item.text }}</li>
</div>
<script src="../../dist/vue.min.js"></script>
<script type="module" crossorigin=“use-credentials”>
var app = new Vue({
el: '#app',
data: {
list: [],
list1: [],
list2: [],
nowDate: '',
updateTime: '',
},
created() {
for (let i = 0; i <= 100000; i++) {
this.list1.push({
id: i,
text: i
})
this.list2.push({
id: i * 2,
text: 100000 - i
})
}
this.list = this.list1
},
methods: {
changeData() {
this.nowDate = Date.now();
this.list = this.list2;
}
},
updated() {
const date = Date.now();
console.log(`updateTime: ${date - this.nowDate}`);
}
})
</script>
</body>
</html>
- с ключом
Добавьте значение ключа в пройденный выше html-код.
<li v-for="item in list" :key="item.id">{{ item.text }}</li>
Суммировать: Скорость без ключа выше. Причины следующие: в приведенном выше примере опущен тот, у которого нет ключа.Накладные расходы на уничтожение и создание дома, просто замените текстовый узел, и все в порядке., тогда как те, у которых есть ключи, должны пройти процесс исправления, и вам нужно выяснить часть элементов, которые можно использовать повторно, исключить те, которые нельзя использовать повторно, и воссоздать новые элементы DOM.
Каковы недостатки не имеют ключа
Поскольку мы обнаружили сверху, это будет быстрее без ключа, то почему мы должны делать с ключом?
1. Без самого ключа проблем нет, но когда в элементах, которые вы проходите, есть компоненты, вы найдете проблемы. Потому что компоненты могут иметь свое собственное состояние. Давайте посмотрим на следующий пример:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<div v-for="(item, index) in list">
<component-a></component-a>
<button @click="deleteInput(index)">删除</button>
</div>
</div>
<script src="../../dist/vue.min.js"></script>
<script type="module" crossorigin=“use-credentials”>
var ComponentA = {
data: function () {
return {
input: 0
}
},
template: '<input v-model="input" />'
}
var app = new Vue({
el: '#app',
data: {
list: ['1', '2', '3'],
},
methods: {
changeData() {
this.nowDate = Date.now();
this.list = this.list2;
},
deleteInput(index) {
this.list.splice(index, 1);
}
},
components: {
ComponentA
}
})
</script>
</body>
</html>
Приведенный выше код очень прост и в основном реализует следующие функции:
1、组件携带有自己状态的input
2、页面遍历子组件生成3个input
Затем нажмите «Удалить» посередине, и результат будет таким:
Желаемый результат:
Вы можете попробовать это после привязки ключа, чего мы и ожидаем.
2. Поскольку ключевые элементы не используются повторно на месте, могут быть достигнуты некоторые эффекты переходной анимации.
Не рекомендуется использовать значение индекса в качестве значения ключа
Обычно нам нравится использовать индекс как индекс ключа, но в этом случае значение ключа теряет свое собственное значение.При встрече с приведенными выше примерами мы также возвращаемся назад и наступаем на яму.
Во многих групповых проектах eslint используется для определения того, использует ли v-for в шаблоне значение ключа. Тем самым снижая процент ошибок. Тогда ключ лучше всего привязать к значению идентификатора, возвращаемому данными.
Суммировать
Эта точка знаний на самом деле очень поверхностна, но она также многое изменила в моем познании.
1. Не нужно много раз писать значение ключа, если это простая отрисовка списка, то думаю не нужно.
2. Когда вы хотите записать значение ключа, лучше не использовать индекс, потому что значение индекса ничем не отличается от повторного использования на месте.
3. Если вы хотите добиться некоторых эффектов перехода, вы можете взглянуть на документацию vue, Там есть несколько готовых эффектов перехода, которые можно использовать напрямую.