Роль Диффа
React Diff поможет нам разобраться, что находится в Virtual DOMЧасть, которая действительно изменилась, и выполняйте фактические манипуляции с DOM только для этой части вместо повторного рендеринга всей страницы.
Проблемы с традиционными алгоритмами сравнения
Традиционный алгоритм сравнения использует циклическую рекурсию для поочередного сравнения узлов, сложность — O(n^3), а эффективность низкая.
Стратегия алгоритма React diff
- Для древовидной структуры (tree diff): игнорируйте межуровневую операцию узлов DOM слоя пользовательского интерфейса. (небольшое количество)
- Для diff компонентов: иметь то же самоеДобрыйДва компонента генерируют похожие древовидные структуры с разнымиДобрыйДва компонента , генерируют разные структуры свойств.
- Для element-diff: для группы узлов на одном уровне используйтеуникальностьидентификатор различия (ключевой атрибут)
Особенности дерева diff
-
React выполняет иерархический обход виртуального дерева DOM с помощью updateDepth.
-
Два дерева сравнивают только узлы на одном уровне.Пока узел не существует, узел и все его дочерние элементы будут заменены.удалить полностью, дальнейшее сравнение не производится.
-
Для сравнения всего дерева DOM требуется только один обход.
React diff учитывает толькотот же уровеньПреобразование позиции узла , если это межуровневое изменение позиции, это операция создания узла и удаления узла. То есть тот же узел воссоздается в новой позиции, а узел в исходной позиции удаляется.
Советы: React официально рекомендует не выполнять межуровневые операции над узлами DOM, а скрывать и отображать узлы через CSS, вместо фактического удаления и добавления узлов DOM, поддержание стабильной структуры DOM поможет повысить производительность.
Особенности diff компонентов
- Для одного и того же типа компонентов сравните виртуальное DOM-дерево в соответствии с исходной стратегией (tree diff).
- Для одного и того же типа компонента компонент A преобразуется в компонент B. Если виртуальный DOM не меняется, вы можете передать
shouldComponentUpdate()
метод, чтобы определить, является ли
Официальная документация React по внедрению shouldComponentUpdate
- Различные типы компонентов, тогда алгоритм сравнения будет оценивать компоненты, подлежащие изменению, как
dirty component
, тем самым заменяя все узлы всего компонента.
Даже если компоненты похожи по структуре, пока React считает, что это разные компоненты, он не будет судить, являются ли они компонентами разных типов, и не будет сравнивать их структуры, а удалит компонент и его подкомпоненты и создать новый компонент и узел его подкомпонентов.
Отличительные особенности элементов
Для узлов одного уровня React diff предоставляет три операции с узлами: вставка, перемещение, удаление.
- Вставка: новый компонент находится не в исходной коллекции, а в совершенно новом узле, и операция вставки выполняется в коллекции.
- Удалить: компонент уже находится в коллекции, но коллекция была обновлена, и в это время необходимо удалить узел.
- Мобильный: Компонентыуже существует вВ коллекции и при обновлении коллекции компонент не обновляется, а меняется позиция, например: (A,B,C,D) → (A,D,B,C), если онатрадиционная разницаКогда обнаруживается, что вторая цифра в старом наборе — B, а вторая цифра в новом наборе — D, удалите B, вставьте D, и все последующие узлы должны быть перезагружены, в то время как React diff — путем добавления узлов в тот же слойуникальный ключМы различаем и двигаемся.
Некоторые движущиеся сцены и логика
Тот же узел, другое место
Начать обход по порядку в новой коллекции
- B в новом наборе lastIndex (аналогично float) = 0, в старом наборе index = 1, index >
lastIndex
Считается, что B не влияет на положение других элементов множества и не перемещается, и тогдаlastIndex
= max(index, lastIndex) = 1 - A имеет индекс = 0 в старом наборе, в этот момент
lastIndex
= 1, удовлетворяют индексу lastIndex, затем выполните операцию перемещения на A, в это времяlastIndex
= max(Index, lastIndex) = 1 - Операции D и B такие же, как и (1), без движения, в это время
lastIndex
=max(index, lastIndex) = 3 - C и A работают так же, как и (2), чтобы двигаться, в это время
lastIndex
= max(index, lastIndex) = 3
Расположение узлов изменилось
1. В той же ситуации, что и выше, B не движется,lastIndex
=1
2. Получить E в новом наборе и обнаружить, что E не существует в старом наборе.lastIndex
где создается Е,lastIndex
++
3. Возьмем С в старом наборе, С не двигается,lastIndex
=2
4. Возьмите А в старом наборе, переместите А на позицию в новом наборе,lastIndex
=2
5. После завершения сравнения всех узлов в новом наборе пройдитесь по старому набору в цикле, чтобы найти узел (D в этом примере), который не существует в новом наборе, но есть в наборе, и удалите узел D. .
Недостатки React diff
В этом примере D напрямую повышается с последней цифры на первую цифру, что приводит кlastIndex
На первом этапе он напрямую обновляется до 3, так что ABC находится в состоянии index последнийУзел повышен доПервыйЕсли рабочая частота высока или количество узлов велико, это повлияет на производительность рендеринга.
резюме
- Разница между React diff и традиционным diff заключается в том, что React улучшает O (n ^ 3) до O (n) за счет оптимизации.
- React оптимизирует различия между деревьями, компонентами и элементами тремя способами.
- Во время разработки старайтесь поддерживать стабильную структуру DOM и сократить операцию перемещения последнего узла в первый, что может оптимизировать производительность рендеринга.
использованная литература
«Погрузитесь в стек React»
Серия анализа исходного кода React - невероятная реакция diff