предисловие
все знакомоVue
Мелкие партнеры в стеке технологий знают, что в сцене рендеринга списка его нельзя использовать.index
илиrandom
так какkey
.
Есть также много мелких партнеров, которых интервьюер расспросит более подробно во время интервью.index
так какkey
В чем будет проблема? Если вы используетеrandom
так какkey
В чем будет проблема? Если вы используете уникальную константуid
так какkey
Каковы преимущества?
Этот вопрос, на первый взгляд, кажется исследованием нашего процесса сравнения с коллегами.diff
Алгоритмическое понимание, единственная константаkey
Это может помочь нам быстрее найти многоразовыеVNode
, чтобы снизить нагрузку на производительность, используйтеindex
так какkey
может привести кVNode
неправильное повторное использование, что приводит кbug
, при использованииrandom
так какkey
приведет кVNode
Его нельзя использовать повторно все время, что сильно влияет на производительность.
Есть ли проблема с этим ответом? нет проблем.
Но если этот вопрос из 100, я могу дать вам только 99 баллов.
а также1分
,относится кVue
更新流程
Если мы не разъясним мелкие детали в статье, это может вызвать у нас проблемы в реальном бизнес-сценарии.
Что вас беспокоит?
взять каштан
Сразу в тему, посмотрите кусок кода,index
так какkey
, если мы удалим определенный элемент, что будет в результате?
<template>
<div id="app">
<div v-for="(item, index) in data" :key="index">
<Child />
<button @click="handleDelete(index)">删除这一行</button>
</div>
</div>
</template>
<script>
export default {
name: "App",
components: {
Child: {
template: '<span>{{name}}{{Math.floor(Math.random() * 1000)}}</span>',
props: ['name']
}
},
data() {
return {
data: [
{ name: "小明" },
{ name: "小红" },
{ name: "小蓝" },
{ name: "小紫" },
]
};
},
methods: {
handleDelete(index) {
this.data.splice(index, 1);
},
}
};
</script>
увидеть результаты
Можно заметить, что хотя мы и не удалили последний, но последний в итоге был удален.Как ни странно, но если вы знаетеVue
изdiff
процесс, этот результат должен соответствовать вашим ожиданиям.
diff
Большие разделы исходного кода столбцов усложнят наше понимание, поэтому я помещаюVue
из更新流程
Упрощенно на картинке:
Вообще говоря, мы говоримVue
изdiff
процесс, что означаетpatchVnode
,вupdateChildren
Это то, что мы называем сравнением на одном уровне, которое на самом деле является сравнением старого и нового.Vnode
множество.
Vue
Четыре переменные указателя будут объявлены для записи нового и старого соответственно.Vnode
Первый и последний индекс массива путем перемещения указателей первого и последнего индекса в соответствии с порядком новой головы и старой головы, новой хвостовой части и старой хвостовой части, старой головы и новой хвостовой части, и старый хвост и новая голова, новое и старое сравниваются по очереди.Vnode
, если не попалsameVnode
, тоoldVnode.key
поддерживать как одинmap
, продолжайте запрашивать, содержит ли онnewVnode.key
, если попалsameVnode
, затем выполнить рекурсивноpatchVnode
. Если он не попал в конце, это означает, что повторное использование невозможно.Vnode
, создать новоеdom
узел.
подобноnewVnode
Указатели головы и хвоста встречаются первыми, указывая на то, чтоnewVnode
Он был пройден и удален непосредственноoldVnode
превышение, еслиoldVnode
Указатели головы и хвоста встречаются первыми, указывая на то, чтоoldVnode
Обход завершен, прямо добавляемnewVnode
избыточная часть.
Такое прямое текстовое описание будет выглядеть бледно, поэтому я подготовил动画
:
первый шаг:
Шаг 2:
третий шаг:
четвертый шаг:
пятый шаг:
Шаг 6:
Теоретически, пока вы скользите достаточно быстро, вы можете подняться на несколько картинок вверх 😊
Изображения, описывающие вышеприведенный процесс updateChildren, взяты изДемистификация технологии Vue обновление компонентаГлава, рекомендуется прочитать исходный текст
Я долго пытался и не мог сделать анимацию.В то же время я чувствовал, что эти картинки могут дать нам достаточно интуитивное ощущение, поэтому я переместил их напрямую.
Вторжение.
использоватьindex
так какkey
в чем будет проблема
Как мы сказали выше, судить о старом и новомVnode
Возможность повторного использования зависит отsameNode
метод, этот метод очень прост, это сравнитьVnode
Некоторые свойства , гдеkey
является самым важным фактором
function sameVnode (a, b) {
return (
a.key === b.key &&
a.asyncFactory === b.asyncFactory && (
(
a.tag === b.tag &&
a.isComment === b.isComment &&
isDef(a.data) === isDef(b.data) &&
sameInputType(a, b)
) || (
isTrue(a.isAsyncPlaceholder) &&
isUndef(b.asyncFactory.error)
)
)
)
}
Вернемся к каштану выше и посмотрим, что пошло не так.
генерируется приведенным выше кодомVNode
Что-то вроде этого:
[
{
tag: 'div',
key: 0,
children: [
{
tag: VueComponent,
elm: 408, // 这个Vnode对应的真实dom是408
},
{
tag: 'button'
}
]
},
{
tag: 'div',
key: 1,
children: [
{
tag: VueComponent,
elm: 227, // 这个Vnode对应的真实dom是227
},
{
tag: 'button'
}
]
}
...
]
Мы удаляем первый фрагмент данных, новыйVNode
Что-то вроде этого:
[
{
tag: 'div',
key: 0,
children: [
{
tag: VueComponent,
elm: 227, // 这个Vnode对应的真实dom是227
},
{
tag: 'button'
}
]
},
{
tag: 'div',
key: 1,
children: [
{
tag: VueComponent,
elm: 324, // 这个Vnode对应的真实dom是324
},
{
tag: 'button'
}
]
}
...
]
насЛогика человеческой плотипосмотри на этих двоихVnode
массив, так какkey
Все равны 0, поэтому при сравнении первого будетsameNode, что приводит к неправильному повторному использованию, тоupdateChildren
, дочерний узелVnode
все еще хитsameVnode
, точно так же попадут второй и третий предметыsameVnode
, прямо злоупотребляя связанной с ним истинойdom
Node, поэтому мы, очевидно, удаляем первый, но производительность пользовательского интерфейса удаляется последним.
Так это заканчивается здесь?
Конечно нет, потому что многие друзья только выходят на связьVue
, также используетсяindex
так какkey
, какие-то офигенные проекты даже запущены, и вроде никто не ищет неприятностей
Зачем?
почему я используюindex
так какkey
нет проблем
Если я изменю код на этот и удалю определенный элемент, каков будет результат?
<template>
<div id="app">
<div v-for="(item, index) in data" :key="index">
<Child :name="`${item.name}`" />
<button @click="handleDelete(index)">删除这一行</button>
</div>
</div>
</template>
увидеть результаты
Фейк, мы явно поставилиVue
из更新流程
понятно, пользуйтесьindex
так какkey
приведет кVnode
Неправильное повторное использование, почему он ведет себя нормально здесь?
давайте посмотрим еще раз更新流程
Упрощенная схема:
тип компонентаVnode
,существуетpatchVnode
будет выполняться в течениеprePatch
Хук-функция для компонентаpropsData
переназначение, которое вызываетsetter
,еслиpropsData
Если значение изменится, сработаетupdate
, чтобы повторно отобразить компонент
мы можем сноваЛогика человеческой плотиТеперь на этот раз мы удаляем второй, потому чтоkey
последовательный, новыйVnode
Массив по-прежнему будет повторно использовать старыйVnode
Первые три элемента массива, первый элементVnode
Правильное повторное использование, компонентыpropsData
Без изменений, не срабатываетupdate
, который напрямую повторно использует связанную с ним истинуdom
узел, а второйVnode
неправильное повторное использование, но компонентpropsData
Изменился с маленького красного на маленький синий, вызывая срабатываниеupdate
, компонент перерисовывается, поэтому мы видим, чтоrandom
Изменения произошли, и третья такая же.
ха~
В этот момент я, наконец, понял, что я действительно умный маленький призрак.
Так это заканчивается здесь?
На самом деле пока нет, например, давайте изменим код
<template>
<div id="app">
<div v-for="(item, index) in data" :key="index">
<span>{{item.name}}</span>
<button @click="handleDelete(index)">删除这一行</button>
</div>
</div>
</template>
увидеть результаты
На этот раз у нас нет типа компонентаVnode
, не будет выполнятьсяprePatch
, почему это все еще нормально?
Посмотрите еще раз на выше更新流程
рисунок, тип текстаVnode
, когда старый и новый тексты различаются, они будут перезаписаны напрямую.
На данный момент мы полностью поняли, почему рекомендуется использовать единственную константу в сцене рендеринга спискаid
так какkey
. Помимо спецификации кода, даже в некоторых сценариях проблема неbug
Форма открыта, но не может быть повторно использована или использована неправильноVnode
, приведет к повторному рендерингу компонента, и нагрузка на производительность этой части по-прежнему очень велика!
последний 1 балл
На бумаге я чувствую себя поверхностным в конце, и я абсолютно точно знаю, что это дело должно быть сделано.
Я прочитал это в первый разVue2
Когда я получил исходный код, я думал, что ясно понял эту часть знаний, пока маленький партнер в команде не задал мне вопрос со списком в виде простого текста.
нужно быть осторожнымdebug
снова更新流程
Считается решенным сомнением в виду, составляют это1分
зазор
Цитата выглядит следующим образом: