Что такое virtual dom
Virtual DOM (виртуальный DOM) — это концепция и технология, используемая в современных JavaScript-фреймворках, таких как React, Vue и других, для повышения производительности обновления пользовательского интерфейса. Виртуальный DOM представляет собой абстракцию реального DOM — облегчённую копию структуры HTML-документа, которая существует в памяти и используется для более эффективного управления обновлениями страницы.
1. Что такое DOM
DOM (Document Object Model) — это объектная модель HTML-документа. Браузер представляет каждую HTML-страницу в виде дерева узлов, где каждый элемент, текст, атрибут — это объект. Изменения DOM (например, изменение текста в <div>, добавление элемента, изменение стиля и т.д.) приводят к:
-
повторному вычислению стилей (recalculate styles),
-
перерасчёту компоновки (reflow),
-
перерисовке (repaint),
-
возможному изменению структуры дерева браузера (layout tree, render tree).
Эти операции дорогие по ресурсам, особенно при частом обновлении DOM. Именно поэтому обновления DOM следует делать как можно реже и эффективнее.
2. Проблема: прямое управление DOM медленно
Когда веб-приложение работает с реальным DOM напрямую, каждое изменение элемента (например, изменение текста кнопки при клике) может вызывать повторную отрисовку. Если таких операций много, страница начинает тормозить.
Всё усложняется, когда:
-
У интерфейса множество зависимостей между элементами.
-
Состояние данных меняется часто (например, в чате, ленте новостей).
-
Нужно поддерживать отзывчивость интерфейса.
Чтобы избежать постоянного взаимодействия с реальным DOM, фреймворки используют виртуальный DOM.
3. Virtual DOM: что это такое
Виртуальный DOM — это объектная структура, которая копирует реальную DOM-структуру, но существует в оперативной памяти и не отображается на экране. Это просто JavaScript-объекты, описывающие структуру интерфейса.
Когда требуется обновить интерфейс:
-
Сначала изменения вносятся во виртуальный DOM.
-
После этого происходит сравнение (diffing) нового и старого виртуального DOM.
-
Вычисляется минимальный набор изменений (patch), который нужно внести в настоящий DOM.
-
Эти изменения применяются к реальному DOM.
Такой подход минимизирует количество операций с реальным DOM, что делает работу интерфейса более эффективной и быстрой.
4. Как устроен Virtual DOM на практике
Представим простой HTML-фрагмент:
<div>
<h1>Hello</h1>
<p>World</p>
</div>
В виртуальном DOM это будет представлено как объект:
{
type: 'div',
props: {},
children: \[
{
type: 'h1',
props: {},
children: \['Hello'\]
},
{
type: 'p',
props: {},
children: \['World'\]
}
\]
}
Каждый элемент представлен узлом с типом, свойствами (атрибутами) и дочерними элементами.
Если изменить <h1>Hello</h1> на <h1>Hi</h1>, фреймворк не будет перерисовывать весь div, а только обновит текст в нужном узле h1, потому что при сравнении виртуальных DOM он увидит, что изменился только текст.
5. Diffing: алгоритм сравнения Virtual DOM
Diffing — это процесс, в котором фреймворк сравнивает два виртуальных дерева: старое и новое. Алгоритм пытается понять:
-
Какие элементы были добавлены.
-
Какие удалены.
-
Какие обновлены (например, изменился текст или атрибуты).
Пример:
// Старый VDOM
const oldVDOM = createElement('ul', {}, \[
createElement('li', { key: 'a' }, 'A'),
createElement('li', { key: 'b' }, 'B')
\]);
// Новый VDOM
const newVDOM = createElement('ul', {}, \[
createElement('li', { key: 'b' }, 'B'),
createElement('li', { key: 'a' }, 'A')
\]);
Фреймворк увидит, что li с ключами a и b поменялись местами. Благодаря ключам он поймёт, что узлы не были удалены и созданы заново, а просто поменяли порядок — это позволит эффективно обновить реальный DOM, не пересоздавая элементы.
6. Patch: применение изменений к настоящему DOM
После diffing-а, создаётся patch — список изменений. Этот список может включать:
-
обновление текста;
-
замена узла;
-
обновление атрибутов (class, id, style и т.д.);
-
вставка или удаление узлов;
-
изменение порядка дочерних элементов.
Этот patch применяет минимальные изменения в DOM, избегая полной перерисовки всего дерева. Это даёт значительный прирост производительности.
7. Почему Virtual DOM быстрее
Несмотря на то, что добавляется «дополнительный шаг» — создание и сравнение виртуального дерева, в реальности это быстрее, чем прямое управление DOM, потому что:
-
операции с JavaScript-объектами в памяти намного быстрее, чем с DOM-элементами;
-
реальный DOM не изменяется до тех пор, пока не будет вычислен точный набор изменений;
-
благодаря использованию ключей и оптимизаций diffing-а, можно избежать ненужной работы.
8. Virtual DOM и React
React — один из фреймворков, который популяризировал концепцию Virtual DOM. Он реализует виртуальное дерево компонентов через вызов функций React.createElement() или синтаксис JSX:
const element = <h1>Hello</h1>;
Внутри React это превращается в виртуальный объект, который можно сравнивать и обновлять без манипуляции реальным DOM до момента рендеринга.
React также использует Fiber — новую архитектуру виртуального DOM (начиная с версии React 16), которая позволяет приостанавливать и возобновлять работу над обновлениями, обеспечивая плавную отрисовку даже в больших приложениях.
9. Virtual DOM в других фреймворках
-
Vue.js также использует Virtual DOM, особенно начиная с Vue 2. Он делает это похожим образом, создавая лёгкие виртуальные представления компонентов.
-
Snabbdom, Inferno, Preact — это более лёгкие библиотеки, реализующие виртуальный DOM отдельно от больших фреймворков.
-
В некоторых случаях Virtual DOM не используется (например, в Svelte), поскольку эти фреймворки компилируют код в нативные операции DOM во время сборки и избегают runtime diffing.
10. Преимущества Virtual DOM
-
Более производительное обновление интерфейса.
-
Упрощение логики UI: разработчику не нужно вручную контролировать, когда обновлять DOM.
-
Позволяет реализовать однонаправленный поток данных, упрощая отладку и тестирование.
-
Обеспечивает предсказуемость и детерминированность — результат зависит только от состояния, а не от текущего состояния DOM.
11. Недостатки Virtual DOM
-
Не всегда быстрее: для очень простых приложений с редкими изменениями можно добиться большей производительности без виртуального DOM.
-
Добавляет сложность и накладные расходы на промежуточное представление (создание, сравнение деревьев).
-
Необходимость изучать архитектуру компонентов и управление состоянием, особенно в таких фреймворках, как React.