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

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску

Виртуальный DOM (англ. англ. virtual DOM) — легковесное JS-представление объектной модели документа (DOM), используемое в декларативных веб-фреймворках, таких как React, Vue.js и Elm[1]. Поскольку создание виртуального DOM происходит относительно быстро, любой фреймворк может выполнять повторную отрисовку виртуального DOM столько раз, сколько необходимо, с относительно низкими затратами. Затем фреймворк может найти различия между предыдущим и текущим виртуальным DOM (этот процесс называется сравнением или diffing) и внести только необходимые изменения в реальный DOM (этот процесс называется согласованием или reconciliation)[2][3]. Хотя технически этот подход медленнее, чем использование чистого JavaScript, он значительно упрощает написание сайтов с большим количеством динамического контента, поскольку разметка напрямую связана с состоянием.

К схожим техникам относятся Glimmer во фреймворке Ember.js и инкрементальный DOM в Angular[4][5].

Исторически API для работы с DOM в JavaScript был неконсистентным в разных браузерах, неудобным в использовании и трудномасштабируемым для крупных проектов. Хотя библиотеки, такие как jQuery, были нацелены на улучшение общей согласованности и эргономики взаимодействия с HTML[6], они также были подвержены повторяющемуся коду, который плохо описывал природу вносимых изменений и отделял логику от разметки.

Выпуск AngularJS в 2010 году привёл к серьёзному сдвигу парадигмы во взаимодействии между JavaScript и HTML благодаря идее «грязной» проверки (dirty checking)[7]. Вместо императивного объявления и уничтожения обработчиков событий и изменения отдельных узлов DOM, отслеживались изменения переменных, а секции DOM помечались как «грязные» и перерисовывались при изменении переменной в их области видимости. Этот «цикл digest» предоставил фреймворк для написания более декларативного кода, который связывал логику и разметку более логичным образом.

Хотя AngularJS стремился предоставить более декларативный опыт, он по-прежнему требовал явной привязки данных к DOM и их отслеживания, а также вызывал опасения по поводу производительности из-за дорогостоящего процесса «грязной» проверки сотен переменных[8]. Для решения этих проблем React стал первой крупной библиотекой, принявшей на вооружение виртуальный DOM в 2013 году. Это устранило как узкие места в производительности (поскольку сравнение и согласование DOM стали относительно дешёвыми операциями), так и сложность привязки данных (поскольку компоненты по сути стали просто объектами)[9]. Другие преимущества виртуального DOM включали повышенную безопасность, поскольку XSS-атаки стали практически невозможными, и лучшую расширяемость, так как состояние компонента было полностью инкапсулировано[10]. Его выпуск также совпал с появлением JSX, который ещё теснее связал HTML и JavaScript с помощью синтаксического расширения, похожего на XML.

После успеха React многие другие веб-фреймворки скопировали общую идею идеального представления DOM в памяти, например, Vue.js в 2014 году, который использовал компилятор шаблонов вместо JSX и имел встроенную гранулярную реактивность[11].

В последнее время виртуальный DOM подвергается критике за медлительность из-за дополнительного времени, необходимого для сравнения и согласования узлов DOM[12]. Это привело к разработке фреймворков без виртуального DOM, таких как Svelte, и фреймворков, которые редактируют DOM «на месте», таких как Angular (начиная со второй версии).

Реализации

[править | править код]

React был пионером в использовании виртуального DOM для декларативного создания компонентов. Узлы виртуального DOM создаются с помощью функции createElement(), но чаще всего они транспилируются из JSX, чтобы сделать написание компонентов более эргономичным[13]. В классовых компонентах React узлы виртуального DOM возвращаются из функции render(), в то время как в функциональных компонентах на основе хуков возвращаемое значение самой функции служит разметкой страницы.

Vue.js использует виртуальный DOM для обработки изменений состояния, но, как правило, разработчики не взаимодействуют с ним напрямую; вместо этого компилятор преобразует HTML-шаблоны в узлы виртуального DOM, что является деталью реализации[14]. Хотя Vue поддерживает написание JSX и пользовательских рендер-функций[15], более типичным является использование компилятора шаблонов, так как в этом случае не требуется этап сборки.

В Svelte нет виртуального DOM. Его создатель, Рич Харрис, назвал виртуальный DOM «чистыми накладными расходами»[16]. Вместо сравнения и согласования узлов DOM во время выполнения, Svelte использует реактивность на этапе компиляции для анализа разметки и генерации JavaScript-кода, который напрямую манипулирует DOM, что значительно повышает производительность[17].

Примечания

[править | править код]
  1. Beginning Elm (англ.). Elm Programming. Дата обращения: 11 декабря 2020.
  2. Virtual DOM and Internals – React (англ.). reactjs.org. Дата обращения: 11 декабря 2020.
  3. React: The Virtual DOM (англ.). Codecademy. Дата обращения: 11 декабря 2020.
  4. google/incremental-dom (англ.), 8 декабря 2020, Дата обращения: 11 декабря 2020
  5. React Virtual DOM vs Incremental DOM vs Ember's Glimmer: Fight (англ.). Auth0 - Blog. Дата обращения: 11 декабря 2020.
  6. openjsf.org, OpenJS Foundation-. The jQuery Object (амер. англ.). Дата обращения: 11 ноября 2024.
  7. Make Your Own AngularJS, Part 1: Scopes And Digest (англ.) (30 января 2014). Дата обращения: 11 ноября 2024. Архивировано 30 января 2014 года.
  8. Utley, Tatum. The death of AngularJS and why you should care (англ.). blog.core10.io. Дата обращения: 11 ноября 2024.
  9. JSConf (30 октября 2013). Pete Hunt: React: Rethinking best practices -- JSConf EU (англ.). Дата обращения: 11 ноября 2024 — YouTube.
  10. Why did we build React? – React Blog (англ.). legacy.reactjs.org. Дата обращения: 11 ноября 2024.
  11. Reactivity in Depth — Vue.js (англ.). v2.vuejs.org. Дата обращения: 11 ноября 2024.
  12. Harris, Rich. Virtual DOM is pure overhead (англ.). svelte.dev (27 декабря 2018). Дата обращения: 11 ноября 2024.
  13. Writing Markup with JSX – React (англ.). react.dev. Дата обращения: 11 ноября 2024.
  14. Rendering Mechanism (англ.). Vue.js.
  15. Render Functions & JSX (англ.). Vue.js.
  16. Dec 27 2018, Rich Harris Thu. Virtual DOM is pure overhead (англ.). svelte.dev (27 декабря 2018). Дата обращения: 11 декабря 2020.
  17. Harris, Rich. Svelte 3: Rethinking reactivity (англ.). svelte.dev (22 апреля 2019). Дата обращения: 11 ноября 2024.