Чому концепція React Virtual DOM вважається більш ефективною, ніж брудна перевірка моделі?


372

Я побачив розмову про реагентів ( Pete Hunt: React: Переосмислення найкращих практик - JSConf EU 2013 ) і спікер зазначив, що брудна перевірка моделі може бути повільною. Але чи не обчислення різниці між віртуальними DOM насправді навіть менш ефективно, оскільки віртуальна DOM у більшості випадків повинна бути більшою, ніж модель?

Мені дуже подобається потенційна сила Virtual DOM (особливо візуалізація на стороні сервера), але я хотів би знати всі плюси і мінуси.


Я думаю, ви могли б згадати цю розмову і на youtube.com/watch?v=-DX3vJiqxm4, де він конкретно розповідає про орієнтири.
inafalcao

Відповіді:


493

Я основний автор модуля віртуального дому , тому я можу відповісти на ваші запитання. Насправді є дві проблеми, які тут потрібно вирішити

  1. Коли я повторно візуалізую? Відповідь: Коли я помічаю, що дані брудні.
  2. Як я можу ефективно відреагувати? Відповідь: Використання віртуального DOM для генерації реального патчу DOM

У React кожен ваш компонент має стан. Цей стан схожий на спостереження, яке ви можете знайти в нокауті або інших бібліотеках стилів MVVM. По суті, React знає, коли потрібно відредагувати сцену, оскільки він може спостерігати, коли ці дані змінюються. Брудна перевірка відбувається повільніше, ніж спостерігається, оскільки ви повинні регулярно опитувати дані та рекурсивно перевіряти всі значення в структурі даних. Для порівняння, встановлення значення стану сигналізуватиме слухачеві про те, що деякий стан змінився, тому React може просто прослухати події зміни у стані та встановити чергу до повторного відтворення.

Віртуальний DOM використовується для ефективного відтворення DOM. Це насправді не пов’язано з брудною перевіркою даних. Ви можете повторно відтворити, використовуючи віртуальний DOM з брудною перевіркою або без неї. Ви маєте рацію в тому, що в обчисленні різниці між двома віртуальними деревами існує деяка накладні витрати, але віртуальна DOM-різниця полягає в розумінні того, що потребує оновлення в DOM, а не в тому, змінилися чи не ваші дані. Насправді алгоритм diff - це сама брудна перевірка, але вона використовується, щоб перевірити, чи замість цього DOM брудний.

Ми прагнемо відновити віртуальне дерево лише тоді, коли стан зміниться. Тож використання спостережуваної для перевірки, чи змінився стан, є ефективним способом запобігання непотрібних повторних проявів, що може спричинити багато непотрібних дерев. Якщо нічого не змінилося, ми нічого не робимо.

Віртуальний DOM приємний тим, що дозволяє нам писати наш код так, ніби ми рендерируем всю сцену. За лаштунками ми хочемо обчислити патч-операцію, яка оновлює DOM так, щоб ми очікували. Тож хоча алгоритм віртуального DOM diff / patch, мабуть, не є оптимальним рішенням , він дає нам дуже приємний спосіб виразити наші програми. Ми просто заявляємо, що саме хочемо, і React / virtual-dom розробить, як зробити так, щоб ваша сцена виглядала так. Нам не потрібно робити ручні маніпуляції з DOM або плутатись з попереднім станом DOM. Нам також не доведеться відтворювати всю сцену, що може бути набагато менш ефективно, ніж її виправлення.


1
Чи реагує React брудна перевірка компонентних реквізитів? Я запитую, тому що немає функції setProps ().
bennlich


1
що було б прикладом такого unnecessary re-renders?
vsync

9
Коли ви говорите "Отже, хоча алгоритм віртуальної DOM diff / patch, мабуть, не є оптимальним рішенням", чи маєте ви на увазі теоретично більш оптимальне рішення?
CMCDragonkai

3
Схоже, це не відповідає на питання. React вимагає використовувати setState для сигналу про те, що стан змінився. Якщо вам це вдалося, this.state.cats = 99вам все одно знадобиться брудна перевірка, щоб перевірити на зміну моделі, так само як Angular брудний перевіряє дерево діапазону $. Це не порівняння швидкості двох методів, це просто твердження, що React не робить брудної перевірки, оскільки натомість у неї встановлений стиль Backbone.
суперлюмінація

133

Нещодавно я прочитав детальну статтю про алгоритм різниці React тут: http://calendar.perfplanet.com/2013/diff/ . З того, що я розумію, те, що робить React швидким, це:

  • Пакетні операції з читання / запису DOM.
  • Ефективне оновлення лише піддерева.

У порівнянні з методом брудної перевірки, ключовими відмінностями ІМО є:

  1. Брудна перевірка моделі : компонент React явно встановлюється як брудний при кожному setStateвиклику, тому тут немає необхідного порівняння (даних). Для брудної перевірки порівняння (у моделях) завжди відбувається у кожному циклі дайджесту.

  2. Оновлення DOM : Операції з DOM дуже дорогі, оскільки зміна DOM також застосовуватиметься та обчислюватиме стилі, макети CSS. Заощаджений час від непотрібних модифікацій DOM може бути довшим, ніж витрачений час, що відрізняється від віртуальної DOM.

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


1
Насправді я також прочитав деякі статті, тому я зараз (принаймні загалом), як це працює, просто хотів з’ясувати, чому це може бути ефективніше, ніж брудна перевірка моделі. І 1) Так, він не порівнює моделі, але порівняє набагато більший віртуальний будинок 2) Ретельна перевірка моделі надає нам можливість оновлювати лише те, що потрібно (як це робить Angular)
Daniil

Я вважаю, що треба порівнювати лише частини віртуального DOM, що відповідають зміненому компоненту, в той час як брудна перевірка відбувається для кожного циклу дайджесту, для всіх значень у всіх областях, навіть якщо нічого не змінилося. Якщо велика кількість даних змінилася, то Virtual DOM був би менш ефективним, але не для малих змін даних.
tungd

1
Якщо говорити про кутовий, оскільки спостерігачі також можуть мутувати стан під час дайджесту, то $scope.$digestвиконується кілька разів за цикл дайджесту, тому це багаторазовий час повного порівняння даних проти разового часу часткового порівняння віртуального дерева DOM.
tungd

4
прикро, що багато розумних розробників вигадують "гори" хитрощів для боротьби з "повільним" DOM ​​тощо, замість того, щоб зосереджувати нашу об'єднану увагу, щоб просто виправити самі браузери та позбутися нас від повільності DOM раз і назавжди. це як використовувати всі ресурси людства для дослідження способів боротьби з раком та покращення життя пацієнта, а не просто виправити сам рак. Посмішки.
vsync

@vsync DOM повинен відображати речі на екрані. Віртуальний DOM не робить. Навіть за умови ідеального виконання DOM створення віртуального DOM буде швидше.
Єхань

75

Мені дуже подобається потенційна сила Virtual DOM (особливо візуалізація на стороні сервера), але я хотів би знати всі плюси і мінуси.

- ОП

React - не єдина бібліотека маніпуляцій DOM. Я закликаю вас зрозуміти альтернативи, прочитавши цю статтю від Auth0, яка включає детальне пояснення та орієнтири. Тут я виділю їх плюси та мінуси, як ви запитали:

Віртуальний DOM React.js

введіть тут опис зображення

ПРОС

  • Швидкий та ефективний алгоритм "відрізняється"
  • Кілька фронтальних (JSX, гіперскрипт)
  • Досить легкий для роботи на мобільних пристроях
  • Багато тяги та розуму
  • Можна використовувати без React (тобто як незалежний двигун)

КОНС

  • Повна копія DOM в пам'яті (вищий обсяг пам’яті)
  • Немає диференціації між статичними та динамічними елементами

Elim.js 'Glimmer

введіть тут опис зображення

ПРОС

  • Швидкий та ефективний алгоритм, що відрізняється
  • Диференціація між статичними та динамічними елементами
  • На 100% сумісний з API Ember (ви отримуєте переваги без великих оновлень існуючого коду)
  • Легке представлення DOM в пам'яті

КОНС

  • Мається на увазі, що використовується тільки в Ембер
  • Доступний лише один фронтенд

Поступовий ДОМ

введіть тут опис зображення

ПРОС

  • Скорочення використання пам'яті
  • Простий API
  • Легко інтегрується з багатьма фронтальними і фреймовими рамками (мається на увазі як шаблон двигуна шаблону від початку)

КОНС

  • Не так швидко, як інші бібліотеки (це сперечається, див. Орієнтири нижче)
  • Менше використання розуму та використання громади

Представлення маніпуляцій DOM ReactJS мені здається мало. Віртуальна DOM ReactJS - це та, яка повністю змінюється, а не фактична DOM - правильна? Я переглядаю оригінальну статтю, на яку посилаються посилання на статтю, і ось що я бачу - teropa.info/images/onchange_vdom_change.svg . teropa.info/blog/2015/03/02/…
smile.al.d.way

35

Ось коментар члена команди Реакти Себастьяна Маркбоге, який проливає трохи світла:

React робить різний на виході (який відомий серіалізаційний формат, атрибути DOM). Це означає, що вихідні дані можуть мати будь-який формат. Це можуть бути незмінні структури даних та стан всередині закритих блоків.

Кутова модель не зберігає еталонної прозорості і тому є по своїй суті змінюваною. Ви мутуєте існуючу модель для відстеження змін. Що робити, якщо у вашому джерелі даних кожен раз є незмінні дані або нова структура даних (наприклад, відповідь JSON)?

Брудна перевірка та Object.observe не працює у стані області закриття.

Ці дві речі очевидно дуже обмежують функціональні зразки.

Крім того, коли складність вашої моделі зростає, робити все більш дорогим стає брудне відстеження. Однак якщо ви відрізняєтесь лише від візуального дерева, як-от React, воно не зростає так сильно, оскільки кількість даних, які ви зможете показувати на екрані в будь-якій точці, обмежена інтерфейсами користувача. Посилання Піта вище охоплює більше переваг для парфумів.

https://news.ycombinator.com/item?id=6937668


2
Насправді щодо останнього абзацу: це має бути неправильно: модель більша за віртуальний купол, оскільки для кожної моделі моделі існує (у більшості випадків) принаймні один елемент віртуального дому (і зазвичай набагато більше одного). Чому я хочу, щоб модель не була показана?
Даніїл

2
Сторінка кешованих колекцій.
кентор

-2

Віртуальний дім не винайдений реагуванням. Він є частиною HTML dom. Він легкий і відокремлений від деталей, що стосуються браузера.

Ми можемо вважати віртуальний DOM локальною та спрощеною копією HTML DOM. Це дозволяє React робити свої обчислення в цьому абстрактному світі та пропускати "справжні" DOM-операції, часто повільні та залежні від браузера. Насправді немає великої різниці між DOM та VIRTUAL DOM.

Нижче наведено моменти, чому використовується Virtual Dom (джерело Virtual DOM в ReactJS ):

Коли ви робите:

document.getElementById('elementId').innerHTML = "New Value" Following thing happens:
  1. Браузер повинен проаналізувати HTML
  2. Він видаляє дочірній елемент elementId
  3. Оновить значення DOM на нове значення
  4. Перерахуйте повторно css для батька та дитини
  5. Оновіть макет, тобто для кожного елемента точні координати на екрані
  6. Обведіть дерево візуалізації та намалюйте його на дисплеї браузера

Перерахунок CSS та змінених макетів використовує складний алгоритм, який впливає на продуктивність.

А також оновлення властивостей DOM, тобто. значення. Це слідує алгоритму.

Припустимо, якщо ви оновите DOM 10 разів безпосередньо, то всі вищезазначені кроки виконуватимуться один за одним, і для оновлення DOM-алгоритмів знадобиться час для оновлення значень DOM.

Ось чому Real DOM повільніше, ніж віртуальний DOM.


3
Про приклад, якщо ви змінюєте dom безпосередньо або через віртуальний dom, то, нарешті, для обох випадків ви змінюєте dom.
magallanes

Так, в обох випадках ми оновлюємо dom, але у випадку віртуального дому він оновлює, зокрема, той ключ (унікально визначений алгоритмом від реакції) лише полем або тегом елементів. В той час як оновлення дому оновлює або повністю оновлює весь будинок.
Hemant Nagarkoti

11
Я бачив цю статтю від hackernoon.com/virtual-dom-in-reactjs-43a3fdb1d130 . Можливо, краще вказати на джерело, якщо ви не автор.
Jinggang

2
"Ось чому Real DOM повільніше, ніж віртуальний DOM." Ні, пане, ви просто помиляєтесь.
Roecrew
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.