предисловие
Когда дело доходит до React, любой, кто его изучил, подумает о двух замечательных функциях, повышающих производительность: виртуальный DOM и алгоритм сравнения. React diff — это ускоритель Virtual DOM, а улучшение и оптимизация его алгоритма — основа полной визуализации интерфейса React и гарантия повышения производительности. Хотя вам не нужно знать его механизм работы при разработке, его понимание поможет вам лучше понять жизненный цикл компонентов React и оптимизировать программы React.
Что означает React diff? Указывает, что React оптимизирован в стиле React для традиционного алгоритма сравнения!
Традиционный алгоритм сравнения
Вычисление минимального количества операций, необходимых для преобразования одной древовидной структуры в другую, является сложной и стоящей задачей.
Традиционный алгоритм diff сравнивает узлы последовательно посредством рекурсии, что неэффективно, а сложность алгоритма достигает O(n^3), где n — общее количество узлов в дереве. Как ужасно O(n^3), а это значит, что если вы хотите показать 1000 узлов, вам нужно выполнить последовательно миллиарды сравнений. Цена слишком высока.
Если React просто вводит алгоритм diff без каких-либо улучшений оптимизации, его эффективность будет далека от производительности, необходимой для внешнего рендеринга.
Поэтому, если вы хотите внедрить идею сравнения в Virtual DOM, вам нужно разработать стабильный и эффективный алгоритм сравнения, и React это сделал!
Итак, как именно работает React diff?
Реагировать на оптимизацию различий
Сложность традиционного алгоритма сравнения составляет O(n^3), что явно не соответствует требованиям производительности. Инженеры Facebook со смелой стратегиейСложность O(n^3) упрощается до O(n), как это сделать?
стратегия сравнения
- Перемещение узлов DOM по иерархиям в веб-интерфейсе происходит очень редко и может быть проигнорировано.
- Два компонента с одним и тем же классом будут генерировать похожие древовидные структуры, а два компонента с разными классами будут генерировать разные древовидные структуры.
- Для группы дочерних узлов одного уровня их можно отличить по уникальному идентификатору.
Основываясь на трех вышеупомянутых стратегиях предпосылок, команда React оптимизирует традиционный алгоритм сравнения на основе трех стратегий («Углубленный стек технологий React» действительно немного сложен для понимания и расплывчат, вот мое собственное понимание после понимания)
- a->tree diff
- b->component diff
- c->element diffd
Стратегия оптимизации а: дерево diff
Основываясь на стратегии сравнения дерева, React создает дерево виртуального DOM.Иерархическое сравнение, иерархический контроль, сравнивайте только узлы в одном цветовом поле (все дочерние узлы одного и того же родительского узла), когда обнаружится, что дочерний узел исчез, удалите узел и все его дочерние узлы напрямую и не будут использоваться для дальнейшего сравнения, на уровне алгоритма Вышеизложенное означает, что вам нужно пройти только один раз, и вы можете завершить сравнение всего дерева DOM, не выполняя ненужных сравнений.
Как показано на рисунке:
принадлежат к одному и тому жеИерархическое сравнение, иерархический контрольТакже будет межуровневое перемещение нод DOM (в React ноды DOM нестабильны и наносят ущерб производительности, поэтому такая ситуация не рекомендуется в разработке), как ее решает React diff? Как показано ниже:
Выше описаны различные категории узлов DOM на одном уровне. React diff использует метод, близкий к «насилию». Вместо того, чтобы соединять ABC непосредственно с узлом D, он удаляет три узла ABC и создает ABC под D. Я не буду здесь делать подробный разбор, если вы хотите понять процесс интуитивно, то рекомендуется прочитатьВ этой статье показан вышеописанный процесс на пути ведения журнала в жизненном цикле.
Стратегия оптимизации b: разница компонентов
React основан на приложениях для сборки компонентов, и стратегия, используемая для сравнения между компонентами, также проста и эффективна.
- Для одного и того же типа компонента существует два типа в зависимости от того, изменился ли виртуальный DOM.Вы можете использовать shouldComponentUpdate(), чтобы определить, изменился ли виртуальный DOM.Если изменений нет, вам не нужно сравнивать, что может сэкономьте много времени. Обновите связанные узлы
- Для компонентов, которые не относятся к одному и тому же типу, компонент оценивается как грязный компонент, тем самым заменяя все дочерние узлы во всем компоненте.
Как показано на рисунке ниже, когда компонент D заменяется компонентом G, даже если эти два компонента имеют схожую структуру, как только React определяет, что D и G являются компонентами разных типов, он не будет сравнивать структуры двух компонентов, а будет напрямую сравнивать их. удалите компонент D и создайте его заново, компонент G и его дочерние элементы. Хотя React diff будет влиять на производительность, когда два компонента относятся к разным типам, но похожи по структуре, как говорится в официальном блоге React: Компоненты разных типов редко имеют одинаковое дерево DOM, поэтому этот экстремальный фактор трудно добиться значительного влияния на процесс разработки. .
И если узел D слева на приведенном выше рисунке просто меняет свое состояние, обновление в порядке.
Стратегия оптимизации c: разница элементов
Все дочерние узлы одного уровня, их можно отличить по ключу ----- и следовать стратегии a, b.
Для алгоритма, который не был оптимизирован, способ добиться замены старого и нового состоит в том, чтобы удалить все A B C D, а затем создать новый B A D C. Такой способ реализации явно фигня.Как оптимизировать React diff? Он идентифицируется путем добавления значения ключа к каждому узлу.
Узлы, содержащиеся в старом и новом наборах, такие, как показано на рисунке выше.Новый и старый наборы сравниваются по diff.Обнаружено, что узлы в новом и старом наборах являются одними и теми же узлами по ключу.Поэтому существует нет необходимости удалять и создавать узлы. Положение узла в середине перемещается и обновляется до положения узла в новом наборе. В это время результат сравнения, данный React, таков: B и D не делают любую операцию, а A и C выполняют операцию перемещения.
Приведенный выше анализ заключается в том, что в старом и новом наборах есть одни и те же узлы, но в разных местах.Что, если есть новые добавленные узлы и есть старые узлы, которые необходимо удалить? Здесь больше нет многословия, как показано ниже:
Преимущества добавления ключа:
Если ключ не добавлен, то консоль выдаст предупреждение при обходе карты.Так как это предупреждение, то это означает, что обход можно осуществить без его добавления, а достигается удалением, созданием и вставкой. Таким образом, вполне возможно, что производительность будет повреждена.Это может помочь алгоритму сравнения React в сочетании с Virtual DOM найти наиболее подходящий способ сравнения и максимизировать эффективное сравнение, то естьМеняй там, где нужно!
Суммировать
- React оптимизирует алгоритм дифференциации деревьев с помощью стратегии иерархической дифференциации;
- React генерирует похожие древовидные структуры через один и тот же класс, а разные классы генерируют разные древовидные структуры и оптимизируют алгоритм сравнения компонентов;
- React оптимизирует алгоритм сравнения элементов, устанавливая уникальную ключевую стратегию;
- React преобразует проблемы сложности O (n3) в проблемы сложности O (n), формулируя смелую стратегию сравнения;
- Предполагается, что поддержание стабильной структуры DOM во время разработки поможет повысить производительность;
Ссылаться на
- «Погрузитесь в стек React»
- Серия анализа исходного кода React - невероятная реакция diff
- Говоря об алгоритме и ключе React diff