Как именно React Virtual DOM быстрее? - PullRequest
6 голосов
/ 16 апреля 2020

Я понимаю, что есть два аргумента в пользу того, что React Virtual DOM быстрее -

  1. Он обновляет ТОЛЬКО те элементы, которые действительно должны быть обновлены (используя diff).

  2. Пакет обновлений, и, следовательно, мы обновляем реальный DOM только один раз. Таким образом, перекраска также выполняется только один раз, что в противном случае было бы сделано несколько раз.

У меня есть вопросы относительно обоих этих пунктов -

  1. Как Насколько я знаю, все современные браузеры достаточно эффективны, чтобы обновлять только необходимые элементы в DOM. Например, если у меня есть два тега «p», и я изменяю текст в одном из тегов p с помощью нажатия кнопки, тогда только этот тег p будет обновляться с помощью safari (я подтвердил это с помощью мигания краски). Так как же пункт 1 является преимуществом, если он уже реализуется браузерами?

  2. Как именно React выполняет пакетную обработку обновлений? В конечном итоге React также должен будет использовать API-интерфейс DOM для обновления реального DOM. Так почему же, если мы напрямую используем API DOM, то изменения не будут пакетированы, тогда как когда React использует его, они будут пакетированы?

Ответы [ 2 ]

2 голосов
/ 17 апреля 2020

Я нашел ответ на свой вопрос.

Ключ в том, чтобы понять цель Virtual DOM.

Сначала мы должны увидеть, какой подход React использует для визуализации компонентов.

Различные javascript платформы используют разные подходы для обнаружения изменений в модели данных и их рендеринга в представлении.

Рассмотрим AngularJS. Когда мы ссылаемся на наши данные в шаблоне Angular, например, в выражении типа {{foo.x}}, Angular не только отображает эти данные, но и создает наблюдатель для этого конкретного значения. Всякий раз, когда что-то происходит в нашем приложении (событие клика, ответ HTTP, тайм-аут), все наблюдатели запускаются Если значение в наблюдателе изменилось, то это значение повторно отображается в пользовательском интерфейсе. Запустив все наблюдатели, AngularJS по сути выясняет, где нужно внести изменения. Процесс запуска этих наблюдателей называется грязной проверкой.

В React используется другой подход. Всякий раз, когда происходит изменение состояния в компоненте React, вместо того, чтобы выяснить, где внести изменения (например, AngularJS), React повторно отображает весь пользовательский интерфейс с нуля (с обновленным состоянием).

Но у этого подхода React есть проблема. Повторная визуализация всего пользовательского интерфейса означает повторную визуализацию всего дерева DOM. Это проблема, потому что обновление DOM является медленным процессом (из-за перекомпоновки и перерисовки).

Вот где вступает в действие React Virtual DOM. Виртуальный DOM - это просто представление Real DOM в виде javascript объекты. Это просто древовидная структура данных простых javascript объектов, которые существуют в памяти. По сравнению с Real DOM рендеринг Virtual DOM выполняется намного быстрее, потому что он никогда не отображается на экране (перекомпоновка или перерисовка не требуется).

Так как же Virtual DOM решает проблему? Когда мы загружаем наше приложение, React создает Virtual DOM, который является точной виртуальной копией Real DOM. Всякий раз, когда в компоненте происходит изменение состояния, вместо повторного рендеринга всего Real DOM, React рендерит полностью новый Virtual DOM (с обновленным состоянием). Затем он выполняет различие между старой Virtual DOM (исходной копией Real DOM) и этой новой Virtual DOM (визуализируемой после изменения состояния), чтобы выяснить изменения между ними, и выполняет ТОЛЬКО эти изменения в Real DOM. Таким образом, весь пользовательский интерфейс повторно визуализируется (путем рендеринга всего нового Virtual DOM), но в Real DOM выполняются только минимально необходимые изменения.

Поэтому, когда говорят, что «Использование Virtual DOM React «обновляет только те элементы, которые необходимо обновить» (пункт 1 в моем вопросе), это означает, что с помощью Virtual DOM React преодолевает ограничения собственного подхода (подхода к отрисовке всего пользовательского интерфейса с нуля).

Этот ответ также объясняет ту же концепцию.

Я видел некоторые ответы, в которых говорится, что манипулирование DOM с помощью React выполняется быстрее, чем использование API DOM, потому что API DOM повторно отображает всего дерева DOM, тогда как React визуализирует только те части дерева DOM, которые необходимо изменить. Это неправда. Все современные браузеры достаточно эффективны, чтобы обновлять только те части дерева DOM, которые необходимо изменить. Это можно проверить с помощью вспыхивания краски в инструментах разработчика браузеров (см. Также ответ и ответ ). Даже если мы предположим, что API-интерфейс DOM повторно отображает все дерево DOM, все же эти рассуждения ложны, поскольку внутренний код самой React должен использовать API-интерфейс DOM для обновления DOM. Если бы API DOM повторно отобразил все дерево DOM, то React также повторно отобразит все дерево DOM, потому что в конечном итоге он также использует API DOM для обновления DOM.


Что касается второго пункта На самом деле, React упрощает пакетирование для нас.

В React, пока чтения выполняются в Real DOM, записи (изменения состояния) не выполняются в Real DOM. Вместо этого записи ставятся в очередь. Затем, когда все наши операции чтения и записи были обработаны, на основе записей создается новый Virtual DOM. Затем проводится различие между старым и новым Virtual DOM, а затем React записывает необходимые изменения в Real DOM для его обновления. Следовательно, в конечном итоге все записи в Real DOM выполняются вместе в одном перекомпоновке.

Но мы также можем вручную, без React, написать наш код таким образом, чтобы сначала были выполнены все чтения, а затем все записи сделанный. React упрощает пакетирование, потому что с React нам не нужно заботиться о совместном чтении и записи, и React автоматически выполняет пакетную запись для нас. Так что React не делает все быстро. Это облегчает жизнь.


В заключение можно сказать, что React на самом деле не быстрее. Легче. Как говорит Пит Хант в этом видео : «React не волшебный c. Точно так же, как вы можете перейти на ассемблер с помощью C и победить компилятор C, вы можете перейти к необработанным операциям DOM и API DOM вызывает и бьет React, если вы этого хотите. Однако использование C или Java или JavaScript - это повышение производительности на порядок, потому что вам не нужно беспокоиться ... о специфике платформы. С React вы можете создавать приложения, даже не задумываясь о производительности, и состояние по умолчанию быстро. ".

В этом post Рич Харрис также утверждает, что это миф, что" Virtual DOM является быстро».

2 голосов
/ 16 апреля 2020

enter image description here

Как только React узнает, какие виртуальные объекты DOM изменились, React обновит только эти объекты в реальном DOM. Это делает производительность намного лучше по сравнению с непосредственным манипулированием реальным DOM. Это делает React выдающимся как высокопроизводительную библиотеку JavaScript.

Относительно пакетного обновления:

React использует механизм пакетного обновления для обновления реального DOM. Следовательно, приводит к увеличению производительности. Это означает, что обновления для реального DOM отправляются партиями, вместо того, чтобы отправлять обновления для каждого отдельного изменения состояния.

Перекрашивание пользовательского интерфейса является наиболее дорогой частью и эффективно реагирует гарантирует, что реальный DOM получает только пакетные обновления для перекрашивания интерфейса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...