react fiber что это

React-three-fiber: повышаем производительность приложений

Бывает так, что ваше приложение обрабатывает графику и нуждается в высокой производительности – например, если это сервис для бронирования мест в зале, который мы показали в одной из прошлых статей. При этом зачастую нужны плавный зум или скроллинг элементов, а также поддержка различных библиотек. Рассмотрим, как сохранить производительность и скорость, на примере работы с библиотекой react-three-fiber.

react fiber что это. Смотреть фото react fiber что это. Смотреть картинку react fiber что это. Картинка про react fiber что это. Фото react fiber что это

React-three-fiber, можно с вами познакомиться?

Если вы еще не работали с react-three-fiber, то вероятно, слышали о библиотеках React и three.js. Указанная библиотека, в свою очередь, дает возможность использовать при работе с three.js подходы React, такие как virtual dom и jsx, при этом не снижая производительность готового приложения.

При взаимодействии с react-three-fiber, как мы отметили выше, может возникнуть необходимость в плавной анимации большого количества элементов. В чем же трудность?

Для начала необходимо задуматься о корне данной проблемы. Для того чтобы создать объект на сцене, мы используем geometry, material и оборачиваем их в mesh. Это выглядит вот так:

Разобрав любой базовый пример использования библиотеки react-three-fiber, вы сможете реализовать что-то подобное. Однако, такой подход применим только в том случае, если вы анимируете небольшое количество элементов. Ограничение во многом зависит от вашего устройства, поэтому возьмем некоторое абстрактное значение. Допустим, n – максимальное число элементов, которые вы можете анимировать с частотой в 60 кадров в секунду.

А если ограничения вызывают негативные чувства?

Как же быть, если элементов больше, чем n? При таком подходе у вас будут возникать проблемы с производительностью, и это будет заметно, так как анимация станет не такой плавной, как мы задумывали. Тут возникает вопрос, как быть дальше. Неужели ничего нельзя сделать и нет выхода?

react fiber что это. Смотреть фото react fiber что это. Смотреть картинку react fiber что это. Картинка про react fiber что это. Фото react fiber что это

К счастью, это не так!

Новый взгляд на вещи

Что же мешает нам? Основная проблема – это создание собственного mesh для каждого объекта на сцене. Из-за этого компьютеру приходится отображать по очереди все наши элементы, один за другим. Но давайте рассмотрим изображение как одну сущность, которая состоит из множества объектов. Представьте, вместо того, чтобы переносить с места на место предметы по отдельности, мы поместим их в какое-то “хранилище” и перенесем за раз.

Именно такой подход и помогает решить проблему с производительностью. Единственное, что нас ограничивает в данной ситуации – для достижения результата необходимо, чтобы все объекты использовали единые geometry и material. Но с таким ограничением можно мириться при решении множества задач.

Вместо тысячи слов

Давайте рассмотрим способы реализации подобного подхода. Для этих целей существует instancedMesh. Что это такое? По сути, это тот же mesh, только он состоит из множества объектов, которые имеют одни и те же geometry и material. Выглядит это вот так:

С виду обычный mesh, но есть ряд особенностей.

Во-первых, наличие ref тут неспроста. Именно с помощью него будет происходить добавление элементов в наш instancedMesh, так как на данном этапе внутри него нет ни одного элемента.

Во-вторых, countOfElements – это число элементов, которое будет добавлено в наш instancedMesh.

Ну и сам процесс добавления:

Давайте пройдем по шагам.

Мы создадим объект tempObject. Он будет нужен нам для формирования матрицы преобразований и всё. Мы берём оттуда матрицу, а объект отображать на сцене не будем.

Далее пройдем по нашему массиву элементов, которые послужат для создания объектов, добавляемых на сцену.

Для каждого элемента получим его координаты x и y, а также уникальные идентификаторы id, которые дадут нам возможность обращаться к элементам при необходимости.

Далее зададим позиционирование для объекта tempObject и обновим ему матрицу трансформаций. Такие трансформации, как смещение, поворот и тому подобные, можно записать в матричном виде и применить их к каждой из координат какого-либо элемента на сцене (подробнее с этим знакомит линейная алгебра).

Затем зададим матрицу для каждого из элементов, к которым планируем обращаться через id. Причём если объекта с данным идентификатором не существует, то он будет создан.

После добавления всех интересующих нас элементов обновим матрицу нашего instancedMesh и увидим изменения. Обратите внимание, что число элементов, которые мы добавляем в наш instancedMesh, должно быть равно тому значению, которое указали в countOfElements.

Подводя итоги

Используя описанный способ оптимизации в одном из наших проектов, мы решили проблему с производительностью, которая возникала при рендеринге большого числа элементов. instancedMesh позволяет повысить производительность приложений и сделать это просто и без лишних проблем.

Спасибо за внимание! Надеемся, что этот опыт был вам полезен.

Источник

Вступление в архитектуру React Fiber

Привет, Хабр! Предлагаю вашему вниманию перевод статьи «React Fiber Architecture» автора Andrew Clark.

Вступление

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

Цель Fiber в увеличении производительности при разработке таких задач как анимация, организация элементов на странице и движение элементов. Ее главная особенность это инкрементный рендеринг: способность разделять работу рендера на единицы и распределять их между множественными фреймами.

Другие ключевые фичи включают возможность приостановки, отмены или переиспользования входящих обновлений DOM дерева, возможность приоритизации разных типов обновлений, а также — согласование примитивов.

Перед прочтением данной статьи рекомендуется ознакомиться с основными принципами React:

Обзор

Что такое сверка (reconciliation)?

Сверка — это алгоритм React, используемый для того, чтобы отличить одно дерево елементов от другого для определения частей, которые нужно будет заменить.

Апдейт — это изменение в данных, которые используются для отрисовки React приложения. Обычно это результат вызова метода setState; конечный результат отрисовки компонента.

Ключевая идея React API — мыслить об апдейтах так, если бы они могли привести к полной отрисовке приложения. Это позволяет разработчику действовать декларативно, а не переживать о том насколько рациональным будет переход приложения из одного состояния в другое (от А до B, B до С, С до A и тд.).

В целом, отрисовка всего приложения на каждое изменение работает только в наиболее традиционных приложениях. В реальном мире это негативно сказывается на производительности. Реакт влючает в себя оптимизации, которые создают представление полной отрисовки, не затрагивая огромную долю производительности. Большую часть этих оптимизаций и включает в себя процесс, называемый сверка.

Сверка — это алгоритм, за которым стоит то, что мы привыкли называть «Virtual DOM». Определение звучит как-то так: когда вы рендерите React приложение, дерево елементов, которое описывает приложение генерируется в зарезервированной памяти. Это дерево потом включается в рендеринг окружение — на примере браузерного приложения, оно переводится в набор DOM операций. Когда состояние приложения обновляется (обычно вызовом setState), новое дерево генерируется. Новое дерево сравнивается с предыдущим, чтоб просчитать и включить именно те операции, которые нужны для перерисовки обновленного приложения.

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

Ключевые понятия:

Сверка против рендеринга

DOM дерево это одно из окружений, которые React может отрисовать, к остальным можно отнести нативные iOS и Android Views с помощью React Native (Вот почему Virtual Dom — название немного неподходящее).

Причина почему React поддерживает так много целей в том что React построен так, что сверка и рендеринг это отдельные фазы. Сверщик, работая, вычисляет какие части дерева изменились, отрисовщик позже использует эту информацию чтобы обновить ранее отрисованное дерево.

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

Fiber – переделанная реализация алгоритма reconciliation. Она имеет непрямое отношение к рендерингу, в то время как механизмы рендеринга (отрисовщики) могут быть изменены чтоб поддерживать все приемущества новой архитектуры.

Планирование — это процесс, который определяет когда работа должна быть выполнена.

Работа — любые вычисления, которые должны быть выполнены. Работа – это обычно результат апдейта (например вызов setState).

Принципы архитектуры React настолько хороши, что могут быть описаны лишь этой цитатой:

В текущей реализации React проходит дерево рекурсивно и вызвает функции рендеринга на всем обновленном дереве в ходе одного тика (16 мс). Однако в будующем он сможет уметь отменять некоторые апдейты чтобы предотвратить скачки фреймов.
Это частообсуждаемая тема касательно React дизайна. Некоторые популярные библиотеки реализуют проталкивающий («push») подход, где вычисления производятся тогда, когда новые данные доступны. Однако, React придерживается подхода протягивания («pull»), где вычисления могут быть отменены когда это необходимо.
Реакт это библиотека не для обработки обобщенных данных. Это библиотека для построения пользовательских интерфейсов. Мы думаем что у него должна быть уникальная позиция в приложении, чтоб определять какие вычисления являются подходящими, а какие нет в данный момент.
Если что-либо за кулисами, значит мы можем отменить всю логику связанную с этим. Если данные приходят быстрее чем норма отрисовки кадров, мы можем обьеденить обновления. Мы можем увеличить приоритет работы, приходящей вследствие взаимодействия с пользователем (такую как появление анимации при нажатии на кнопку) против менее важной работы на бэкграунде (отрисовка нового контента подгруженного с сервера), чтобы предотвратить скачки фреймов.

Ключевые понятия:

Реакт на данный момент не имеет приемущества планирования в значитильной мере; результаты обновлений всего поддерева будут отрисовываться незамедлительно. Тщательный отбор елементов в алгоритме ядра React, чтобы применить планирование – ключевая идея Fiber.

Что же такое Fiber?

Мы будем обсуждать сердце архитектуры React Fiber. Fiber — это более низкоуровневая абстракция над приложением чем разработчики привыкли считать. Если вы считаете свои попытки понять ее безнадежными, не чувствуйте себе обескураженными (вы не одни). Продолжайте искать и это в конце-концов даст свои плоды.

Мы достигли той главной цели архитектуры Fiber — позволить React воспользоваться планированием. Конкретно, нам нужно иметь возможность:

Чтобы все это сделать нам сначала потребуется разделить работу на единицы (units). В некотором смысле это и есть fiber (волокно). Волокно представляет единицу работы.

Чтобы продвинуться далее давайте вернемся к основной концепции React «компоненты как данные функций», часто выражаемые как:

C этим следует то, что рендеринг React приложения похож на вызов функции чье тело содержит вызовы других функций и так далее. Эта аналогия полезна когда думаешь о волокнах.

Способ по которому компьютеры в основном проверяют порядок выполнения программы называется стек вызова (call stack). Когда функция выполненена, новый стек-сонтейнер добавляется в стек. Этот стек-контейнер представляет собой работу проделанную функцией.

При работе с пользовательскими интерфейсами, слишком много работы выполняется сразу и это проблема, это может привести к скачкам анимации и будет выглядеть прерывисто. Более того, некоторая из этой работы может быть необязательна если она заменена наиболее новым обновлением. В этом месте сравнение между пользовательским интерфейсом и функцией расходится, потому что у компонентов более специфичная ответственность чем у функций вообще.
Новейшие браузеры и React Native реализует APIs, которые помогают решить эту проблему:
requestIdleCallback распределяет задачи так, чтоб низкоприоритезированные функции вызывались в простой период, а requestAnimationFrame распределяет задачи, чтоб высокоприоритезированные функции были вызваны в следующем кадре. Проблема в том, чтоб использовать эти APIs вам нужно разделить работу отрисовки на инкрементируемые единицы. Если вы полагаетесь только на стек вызовов, работа продолжится пока стек не будет пуст.

Не было бы прекрасно если бы мы могли настроить поведение стека вызовов чтоб оптимизировать отображение частей пользовательского интерфейса? Было бы здорово если бы мы могли прервать стек вызова, чтобы манипулировать контейнерами вручную?

Это и есть призвание React Fiber. Fiber — это новая реализация стека, подстроенная под React компоненты. Вы можете думать об одном волокне как о виртульном стек-контейнере.

Приемущество данной реализации стека в том что вы можете сохранить стек контейнеры в памяти и выполнить тогда (и где) вы хотите. Это решающее определение для достижения целей планирования.

Кроме планировния, мануальные действия со стеком раскрывают потенциал таких понятий как согласованность (concurrency ) и обработка ошибок (error boundaries).

В следующей секции мы рассмотрим структуру волокон.

Структура «волокна»

Если говорить конкретно, то «волокно» это JavaScript обьект, который содержит информацию о компоненте, его вводе и выводе.

Волокно согласовано со стек-контейнером, но также оно согласовано с сущностью компонета.

Вот несколько важных свойств присущих «волокну» (Этот список не исчерпывающий):

Тип и ключ

Тип и ключ служат волокну так же как и React элементы. Фактически, когда волокно создается, эти два поля копируются ему напрямую.

Тип волокна описывает компонент, которому оно соответствует. Для композиции компонентов, тип это функция или класс компонента. Для служебных компонентов (div, span) тип — это строка.

Концептуально, тип – это функция, выполнение которой прослеживается стек-контейнером.

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

Ребенок и родственник (child and sibling)

Эти поля указывают на другие волокна, описывая рекурсивную структуру волокон.

Ребенок волокна соответсвует значению, которое было возвращено вследствие вызова метода render у компонента. В примере ниже:

Ребенок волокна Parent соответвует Child.

Поле родственник (или сосед) применяется в тех случаях если render возвращает несколько детей (новая особенность в Fiber):

Дочерние волокна это односвязный список во главе которого первый дочерний элемент. Так что в этом примере, ребенок Parent это Child1, а родственники Child1 это Child2.

Вернемся к нашей аналогии с функциями, вы можете думать о дочернем волокне, как о функции вызываемой в конце (tail-called function).

Пример из Википедии:

В этом примере tail-called function это b.

Возвращаемое значение (return)

Возвращаемое волокно — это волокно к которому должа вернуться программа после обработки текущего волокна. Это тоже самое что и вернуть адрес стек-сонтейнера.
Это так же можно считать родительским волокном.

Если волокно имеет несколько дочерних волокон, return каждого дочернего волокна возвращает волокно являющееся родителем. В примере выше, возвращаемое волокно у Child1 и Child2 это Parent.

Текущие и кэшированные свойства (pendingProps и memorizedProps)

Концептуально, свойства — это аргументы функции. Текущие свойства волокна это набор этих свойств в начале выполнения, закешированые — это набор в конце выполнения.

Когда входящие свойства ожидания равны закешированым, это значит что предыдущий вывод волокна может быть переиспользован без проделывания каких-либо вычислений.

Приоритет текущей работы (pendingWorkPriority )

Количество определяющей приоритет работы отображается волокном. Модуль уровня приоритета в React ReactPrioritylevel включает разные уровни приоритетов и что они представляют.

Начиная с исключения типа NoWork, которое равно 0, большее число определяет низший приоритет. Например, вы можете использовать следующую функцию чтоб проверить если приоритет волокна больше чем заданный уровень:

Эта функция только для иллюстрации; она не часть базы React Fiber.

Планировщик использует поле приоритета чтоб найти следующую единицу работы которую можно выполнить. Этот алгоритм мы обсудим в следующей секции.

Альтернатива (или пара)

Обновление (flush) волокна — это значит отобразить его вывод на экране.

Волокно в разработке (work-in-progress) — волокно которое еще не было построено; другими словами – это стек-контейнер, который еще не был возвращен.

В любое время, сущность компонента имеет не более двух состояний для волокна которому соответствует: волокно в текущем состоянии, обновленное волокно или волокно в разработке.

Текущему волокну следует волокно разрабатываемое, а за тем, в свою очередь, волокно обновленное.

Следующее состояние волокна создается лениво с помощью функции cloneFiber. Практически всегда при создании нового обьекта, cloneFiber сделает попытку переиспользовать алтернативу (пару) волокна если она существует, минимизируя при этом затраты ресурсов.

Вам следует думать о поле пара (или альтернатива) как о детали реализации, но она всплывает так часто в документации, что не упомянуть ее было просто невозможно.

Вывод — это служебный елемент (или набор служебных элементов); ноды-листья React приложения. Они специфичны для кажого окружения отображения (например в браузере это ‘div’, ‘span’ и тд.). В JSX они обозначаються как строчные имена тегов.

Итог: Рекомендую попробовать особенности новой архитектуры React v16.0

Источник

Немного о том, как работает виртуальный DOM в React

react fiber что это. Смотреть фото react fiber что это. Смотреть картинку react fiber что это. Картинка про react fiber что это. Фото react fiber что это

Настоящий или реальный (real) DOM

DOM расшифровывается как Document Object Model (объектная модель документа). Проще говоря, DOM — это представление пользовательского интерфейса (user interface, UI) в приложении. При каждом изменении UI, DOM также обновляется для отображения этих изменений. Частые манипуляции с DOM негативно влияют на производительность.

Что делает манипуляции с DOM медленными?

DOM представляет собой древовидную структуру данных. Поэтому изменения и обновления самого DOM являются достаточно быстрыми. Но после изменения обновленный элемент и все его потомки (дочерние элементы) должны быть повторно отрисованы (отрендерены) для обновления UI приложения. Повторный рендеринг — очень медленный процесс. Таким образом, чем больше у нас компонентов UI, тем более дорогими с точки зрения производительности являются обновления DOM.

Манипуляции с DOM являются сердцем современного интерактивного веба. К сожалению, они намного медленнее большинства JavaScript-операций. Ситуация усугубляется тем, что многие JavaScript-фреймворки обновляют DOM чаще, чем необходимо.

Допустим, у нас имеется список из 10 элементов. Мы изменяем первый элемент. Большинство фреймворков перестроят весь список. Это в 10 раз больше работы, чем требуется! Только 1 элемент изменился, остальные 9 остались прежними.

Перестроение списка — это легкая задача для браузера, но современные веб-сайты могут осуществлять огромное количество манипуляций с DOM. Поэтому неэффективное обновление часто становится серьезной проблемой. Для решения данной проблемы команда React популяризовала нечто под названием виртуальный (virtual) DOM (VDOM).

Виртуальный DOM

В React для каждого объекта настоящего DOM (далее — RDOM) существует соответствующий объект VDOM. VDOM — это объектное представление RDOM, его легковесная копия. VDOM содержит те же свойства, что и RDOM, но не может напрямую влиять на то, что отображается на экране.

Виртуальный DOM (VDOM) — это концепция программирования, где идеальное или «виртуальное» представление UI хранится в памяти и синхронизируется с «реальным» DOM, используемая такими библиотеками, как ReactDOM. Данный процесс называется согласованием (reconcilation).

Манипуляции с RDOM являются медленными. Манипуляции с VDOM намного быстрее, поскольку они не отображаются (отрисовываются) на экране. Манипуляции с VDOM похожи на работу с проектом (или планом) здания перед началом его возведения.

Почему VDOM является более быстрым?

Когда в UI добавляются новые элементы, создается VDOM в виде дерева. Каждый элемент является узлом этого дерева. При изменении состояния любого элемента, создается новое дерево. Затем это новое дерево сравнивается (diffed) со старым.

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

На изображениях ниже представлено виртуальное DOM-дерево и процесс согласования.

react fiber что это. Смотреть фото react fiber что это. Смотреть картинку react fiber что это. Картинка про react fiber что это. Фото react fiber что это

Красным цветом обозначены узлы, которые были обновлены. Эти узлы представляют элементы UI, состояние которых изменилось. После этого вычисляется разница между предыдущей и текущей версиями виртуального DOM-дерева. Затем все родительское поддерево подвергается повторному рендерингу для представления обновленного UI. Наконец, это обновленное дерево используется для обновления RDOM.

react fiber что это. Смотреть фото react fiber что это. Смотреть картинку react fiber что это. Картинка про react fiber что это. Фото react fiber что это

Как React использует VDOM?

После того, как мы рассмотрели, что такое VDOM, настало время поговорить о том, как он используется в React.

1. React использует паттерн проектирования «Наблюдатель» (observer) и реагирует на изменения состояния

В React каждая часть UI является компонентом и почти каждый компонент имеет состояние (state). При изменении состояния компонента, React обновляет VDOM. После обновления VDOM, React сравнивает его текущую версию с предыдущей. Этот процесс называется «поиском различий» (diffing).

После обнаружения объектов, изменившихся в VDOM, React обновляет соответствующие объекты в RDOM. Это существенно повышает производительность по сравнению с прямыми манипуляциями DOM. Именно это делает React высокопроизводительной библиотекой JavaScript.

2. React использует механизм пакетного (batch) обновления RDOM

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

Повторная отрисовка UI — самая затратная часть, React обеспечивает точечную и групповую перерисовку RDOM.

3. React использует эффективный алгоритм поиска различий

React использует эвристический O(n) (линейный) алгоритм, основываясь на двух предположениях:

Два элемента разных типов приводят к построению разных деревьев

Разработчик может обеспечить стабильность элементов между рендерингами посредством пропа key (ключ)

На практике эти предположения являются верными почти во всех случаях.

При сравнении двух деревьев, React начинает с корневых элементов. Дальнейшие операции зависят от типов этих элементов.

Элементы разных типов

Если корневые элементы имеют разные типы, React уничтожает старое дерево и строит новое с нуля

Любые компоненты, являющиеся дочерними по отношению к корневому, размонтируются, их состояние уничтожается. Например, при сравнении:

Старый Counter будет уничтожен и создан заново.

Элементы одинакового типа

При сравнении двух элементов одинакового типа, React «смотрит» на атрибуты этих элементов. Узлы DOM сохраняются, изменяются только их атрибуты. Например:

После обработки узла DOM, React рекурсивно перебирает всех его потомков.

Рекурсивный перебор дочерних элементов

По умолчанию React перебирает два списка дочерних элементов DOM-узла и генерирует мутацию при обнаружении различий.

Например, при добавлении элемента в конец списка дочерних элементов, преобразование одного дерева в другое работает хорошо:

Обычно, вставка элемента в начало списка плохо влияет на производительность. Например, преобразование одного дерева в другое в данном случае будет работать плохо:

Использование ключей

Теперь React знает, что элемент с ключом 0 является новым, а элементы с ключами 1 и 2 старыми.

На практике в качестве ключей, как правило, используются идентификаторы:

При отсутствии идентификаторов, их всегда можно добавить в модель данных или создать хэш на основе какой-либо части данных. Ключи должны быть уникальными среди соседних элементов, а не глобально.

В крайнем случае, в качестве ключей можно использовать индексы массива. Это работает хорошо только в том случае, если порядок элементов остается неизменным. Изменение порядка элементов будет медленным.

Изменение порядка элементов при использовании индексов в качестве ключей также может привести к проблемам с состоянием элементов. Экземпляры компонента обновляются и повторно используются на основе ключей. Если ключом является индекс, перемещение элемента приведет к изменению ключа. Как результат, состояние компонента для таких вещей, как неуправляемое поле для ввода данных, может смешаться и обновиться неожиданным образом.

Простыми словами: «Вы говорите React, в каком состоянии должен находиться UI, и он обеспечивает соответствие DOM этому состоянию. Преимущество такого подхода состоит в том, что вам, как разработчику, не нужно знать, как именно происходит изменение атрибутов, обработка событий и обновление DOM».

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

Поскольку «виртуальный DOM» — это в большей степени паттерн, нежели конкретная технология, данное понятие может означать разные вещи. В мире React «виртуальный DOM», обычно, ассоциируется с React-элементами, которые являются объектами, представляющими пользовательский интерфейс. Тем не менее, React также использует внутренние объекты, которые называются «волокнами» (fibers). В этих объектах хранится дополнительная информация о дереве компонентов. Fiber — это новый движок согласования, появившийся в React 16. Его основная цель заключается в обеспечении инкрементального рендеринга VDOM.

Как выглядит VDOM?

Название «виртуальный DOM» делает концепцию немного магической (мистической). На самом деле, VDOM — это обычный JavaScript-объект.

Представим, что у нас имеется такое DOM-дерево:

react fiber что это. Смотреть фото react fiber что это. Смотреть картинку react fiber что это. Картинка про react fiber что это. Фото react fiber что это

Это дерево может быть представлено в виде такого объекта:

Это наш VDOM. Как и RDOM, он является объектным представлением HTML-документа (разметки). Однако, поскольку он представляет собой всего лишь объект, мы можем свободно и часто им манипулировать, не прикасаясь к RDOM без крайней необходимости.

VDOM под капотом

Теперь давайте поговорим о том, как VDOM решает проблему производительности и повторного использования.

Как мы выяснили ранее, VDOM может использоваться для обнаружения конкретных изменений, которые необходимо произвести в DOM. Вернемся к примеру с неупорядоченным списком и внесем в него те же изменения, которые мы делали с помощью DOM API.

Первым делом, нам нужна копия VDOM с изменениями, которые мы хотим осуществить. Поскольку нам не нужно использовать DOM API, мы можем просто создать новый объект.

Данная копия используется для создания «различия» (diff) между оригинальным VDOM ( list ) и его обновленной версией. Diff может выглядеть следующим образом:

Данный diff содержит инструкции по обновлению RDOM. После определения всех различий мы можем отправить их в DOM для выполнения необходимых обновлений.

Например, мы можем перебрать все различия и либо добавить нового потомка, либо обновить существующего в зависимости от различия:

Обратите внимание, что это очень упрощенная версия того, как может работать VDOM.

VDOM и фреймворки

Обычно, мы имеем дело с VDOM при использовании фреймворков.

Копцепция VDOM используется такими фреймворками, как React и Vue для повышения производительности обновления DOM. Например, с помощью React наш компонент list может быть реализован следующим образом:

Для обновления списка достаточно создать новый шаблон и снова передать его ReactDOM.render() :

Поскольку React использует VDOM, даже несмотря на то, что мы повторно рендерим весь список, обновляются только фактически изменившиеся части.

Заключение

VDOM, определенно, заслуживает нашего внимания. Он предоставляет отличный способ отделения логики приложения от DOM-элементов, уменьшая вероятность непреднамеренного создания узких мест, связанных с манипуляцией DOM. Другие библиотеки так или иначе используют такой же подход, мы наблюдаем становление данной концепции в качестве предпочтительной стратегии разработки веб-приложений.

Облачные VDS от Маклауд быстрые и безопасные.

Зарегистрируйтесь по ссылке выше или кликнув на баннер и получите 10% скидку на первый месяц аренды сервера любой конфигурации!

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *