Что такое виртуальный DOM?


156

Недавно я посмотрел на фреймворк Facebook React . Он использует концепцию под названием «виртуальный DOM», которую я не совсем понял.

Что такое виртуальный DOM? Каковы преимущества?


2
Я считаю, что Virtual DOM говорит об узлах, которые не входят в нормальный DOM.
Derek 朕 會 功夫

8
Я согласен с вышеизложенным мнением относительно модерации. Более того, я считаю, что это очень актуальный и полезный вопрос. «Виртуальный DOM» часто упоминается, но редко определяется.
btiernay

@Rachael: Ресурс, на который вы ссылаетесь, не содержит слова «Virtual DOM» и не описывает его преимущества. Так что это действительно не помогает ответить на вопрос OP.
blerontin

Ответы:


214

React создает дерево настраиваемых объектов, представляющих часть DOM. Например, вместо создания фактического элемента DIV, содержащего элемент UL, он создает объект React.div, содержащий объект React.ul. Он может очень быстро манипулировать этими объектами, фактически не касаясь реальной DOM или проходя через DOM API. Затем, когда он отображает компонент, он использует эту виртуальную DOM, чтобы выяснить, что ему нужно делать с реальной DOM, чтобы два дерева совпали.

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


2
Можно ли это использовать для всего DOM, а не только для его части?
hipkiss 06

8
Это в основном абстракция над абстракцией, которая в конце концов, что реагирует, ищет ссылку в своем дереве объектной модели, выбирает реальный узел в html и возится с ним. Звук отличный virtual dom, но в нем нет ничего вычурного и преувеличенного.
syarul

2
Что вы имеете в виду под «для этого не требуются все тяжелые части, которые входят в настоящий DOM» - тяжелые части?
Ajay S

2
@AjayS управлять реальным DOM не очень эффективно, поэтому его называют тяжелым API. Управление объектами в памяти происходит намного быстрее и эффективнее, а обновление измененной части DOM также более эффективно и быстрее.
jcubic

46

Возьмем пример, хотя и очень наивный: если у вас что-то пошло не так в комнате вашего дома, и вам нужно ее убрать, что будет вашим первым шагом? Будете ли вы убирать свою комнату или весь дом? Ответ: вы будете убирать только ту комнату, которая требует уборки. Это то, что делает виртуальный DOM.

Обычный JS просматривает или отображает всю DOM вместо визуализации только той части, которая требует изменений.

Поэтому всякий раз, когда у вас есть какие-либо изменения, например, вы хотите добавить еще один <div>в свою DOM, будет создана виртуальная DOM, которая фактически не вносит никаких изменений в фактическую DOM. Теперь с этим виртуальным DOM вы будете проверять разницу между этим и вашим текущим DOM. И только другая часть (в данном случае новая <div>) будет добавлена ​​вместо повторного рендеринга всей DOM.


23

Что такое виртуальный DOM?

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

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

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

Метод рендеринга компонента возвращает некоторую разметку, но это еще не окончательный HTML. Это представление в памяти того, что станет реальными элементами (это шаг 1). Затем этот вывод будет преобразован в настоящий HTML, который отображается в браузере (это шаг 2).

Так зачем же проходить через все это для создания виртуальной модели DOM? Простой ответ - это то, что позволяет быстро реагировать. Он делает это посредством виртуального различения DOM. Сравнение двух виртуальных деревьев - старого и нового - и внесение только необходимых изменений в реальный DOM.

Источник из Intro To React # 2


19

virtual DOM(VDOM) не является новой концепцией: https://github.com/Matt-Esch/virtual-dom .

Стратегия VDOM заключается в обновлении DOM без перерисовки всех узлов в одностраничном приложении. Найти узел в древовидной структуре просто, но дерево DOM для приложения SPA может быть огромным. Поиск и обновление узла / узлов в случае события неэффективно по времени.

VDOM решает эту проблему, создавая абстракцию высокого уровня реального dom. VDOM - это легкое дерево высокого уровня, представляющее реальную модель DOM в памяти.

Например, рассмотрите возможность добавления узла в DOM; реагировать сохранить копию VDOM в памяти

  1. Создайте VDOM с новым состоянием
  2. Сравните его со старым VDOM, используя различие.
  3. Обновляйте только разные узлы в реальной DOM.
  4. Назначьте новый VDOM как старый VDOM.

высокий лейбл или высокий уровень?
Душман

8

Это краткое описание и повторение виртуального DOM, часто упоминаемого вместе с ReactJS.

DOM (объектная модель документа) - это абстракция структурированного текста, что означает, что она состоит из кода HTML и CSS. Эти HTML-элементы становятся узлами в DOM. Существуют ограничения на предыдущие методы управления DOM. Виртуальный DOM - это абстракция буквального HTML DOM, созданного задолго до того, как был создан или использован React, но для наших целей мы будем использовать его совместно с ReactJS. Виртуальная модель DOM легковесна и отделена от реализации DOM в браузере. Виртуальный DOM - это, по сути, снимок экрана (или копия) DOM в определенный момент времени. Можно взглянуть на это с точки зрения разработчиков: DOM - это производственная среда, а Virtual DOM - это локальная среда (dev). Каждый раз, когда данные изменяются в приложении React, создается новое виртуальное представление DOM пользовательского интерфейса.

Самый простой метод, необходимый для создания статического компонента в ReactJS:

Вы должны вернуть код из метода рендеринга. Вы должны преобразовать каждый класс в className, поскольку класс является зарезервированным словом в JavaScript. Помимо более серьезных изменений, существуют незначительные различия между двумя DOM, включая три атрибута, которые появляются в Virtual DOM, но не в HTML DOM (key, ref и dangerousSetInnerHTML).

При работе с Virtual DOM важно понимать разницу между ReactElement и ReactComponent.

ReactElement

  • ReactElement - это легкое неизменяемое виртуальное представление элемента DOM без сохранения состояния.
  • ReactElement - это основной тип в React, который находится в виртуальной DOM.
  • ReactElements можно отображать в HTML DOM

    var root = React.createElement('div'); ReactDOM.render(root, document.getElementById('example'));

  • JSX компилирует HTML-теги в ReactElements

    var root = <div/>; ReactDOM.render(root, document.getElementById('example'));

ReactComponent

  • ReactComponent - ReactComponent - это компоненты с отслеживанием состояния.
  • React.createClass считается ReactComponent.
  • При изменении состояния компонент перерисовывается.

Всякий раз, когда ReactComponent имеет изменение состояния, нам нужно как можно меньше изменений в HTML DOM, чтобы ReactComponent был преобразован в ReactElement, который затем можно было вставить в виртуальную DOM, быстро и легко сравнить и обновить.

Когда React знает разницу - он конвертируется в код низкого уровня (HTML DOM), который выполняется в DOM.


4

Это изящная концепция: вместо того, чтобы напрямую манипулировать DOM, который подвержен ошибкам и полагается на изменяемое состояние, вы вместо этого выводите значение, называемое Virtual DOM. Virtual DOM затем сравнить при с текущим состоянием DOM, который генерирует список операций DOM , которые сделали бы текущий вид DOM , как новый. Эти операции применяются быстро в пакетном режиме.

Взято отсюда.


2

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


При чем тут абстракция? слово абстракция здесь не имеет значения
eladcm

0

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


0

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

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

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

Blueprint пришел на помощь, чтобы достичь этого. Рисуем новый чертеж и сравниваем разницу с исходным. Это позволяет нам узнать, какая часть была изменена, а какая осталась прежней. Затем мы вносим необходимые изменения в реальную комнату (обновляем измененные узлы в реальной DOM). Ура.

(Кто-то может подумать, почему мы должны полагаться на виртуальную, а не напрямую сравнивать реальную DOM? Ну, по аналогии, сравнение реальной DOM означает, что вам нужно создать еще одну реальную комнату и сравнить ее с исходной . Это слишком дорого.)


0

Структурной единицей React является компонент. У каждого компонента есть состояние. Всякий раз, когда состояние компонента изменяется, React изменяет дерево V-DOM. После этого последняя версия V-DOM сравнивается с предыдущей версией V-DOM. После этого вычисления (сравнения), когда React знает, какие объекты V-DOM были изменены, он изменяет только те объекты в R-DOM.

С точки зрения непрофессионала,

Скажем, я добавил элемент div в DOM, React создает копию V-DOM без изменения всей R-DOM. Эта недавно созданная V-DOM сравнивается со старой V-DOM. Он обновляет только разные узлы в реальной DOM. Теперь только что созданная V-DOM считается предыдущей версией предстоящей V-DOM.

PS 1. Итак, в отличие от простого js, создается целая новая версия V-DOM и частично обновляется R-DOM. 2. React не обновляет каждое изменение состояния, скорее, обновления R-DOM отправляются пакетами.


0

Согласно документу React: https://reactjs.org/docs/faq-internals.html#what-is-the-virtual-dom

«В мире React термин« виртуальная модель DOM »обычно ассоциируется с элементами React, поскольку они являются объектами, представляющими пользовательский интерфейс. '

import React, { Component } from 'react'; //You need to do this inside a module to import

class App extends Component{
   render(){
       return (
       <button>Hi</button> //This returns a virtual DOM
       )
   }
}

Код внутри return на самом деле является вызовом функции React.createElement:

//render can be rewritten like this:
render(){
   return [
            React.createElement(
                'button',
                {
                    key: null,
                    ref: null,           
                },
                'Hi',
            )
   ]
}

который возвращает что-то вроде этого:

{
  $$typeof: Symbol.for('react.element'), 
  type: "button", 
  key: null, 
  ref: null, 
  props: { 
     children: 'Hi',
  }
}

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

document.createElement('button');

который также является объектом JavaScript, выглядит так:

accessKey: ""
ariaAtomic: null
ariaAutoComplete: null
ariaBusy: null
ariaChecked: null
ariaColCount: null
ariaColIndex: null
ariaColSpan: null
ariaCurrent: null
ariaDescription: null
ariaDisabled: null
ariaExpanded: null
ariaHasPopup: null
ariaHidden: null
ariaKeyShortcuts: null
ariaLabel: null
ariaLevel: null
ariaLive: null
ariaModal: null
ariaMultiLine: null
ariaMultiSelectable: null
ariaOrientation: null
ariaPlaceholder: null
ariaPosInSet: null
ariaPressed: null
ariaReadOnly: null
ariaRelevant: null
ariaRequired: null
ariaRoleDescription: null
ariaRowCount: null
ariaRowIndex: null
ariaRowSpan: null
ariaSelected: null
ariaSetSize: null
ariaSort: null
ariaValueMax: null
ariaValueMin: null
ariaValueNow: null
ariaValueText: null
assignedSlot: null
attributeStyleMap: StylePropertyMap {size: 0}
attributes: NamedNodeMap {length: 0}
autocapitalize: ""
autofocus: false
baseURI: "http://localhost:3000/"
childElementCount: 0
childNodes: NodeList []
children: HTMLCollection []
classList: DOMTokenList [value: ""]
className: ""
clientHeight: 0
clientLeft: 0
clientTop: 0
clientWidth: 0
contentEditable: "inherit"
dataset: DOMStringMap {}
dir: ""
disabled: false
draggable: false
elementTiming: ""
enterKeyHint: ""
firstChild: null
firstElementChild: null
form: null
formAction: "http://localhost:3000/"
formEnctype: ""
formMethod: ""
formNoValidate: false
formTarget: ""
hidden: false
id: ""
innerHTML: ""
innerText: ""
inputMode: ""
isConnected: false
isContentEditable: false
labels: NodeList []
lang: ""
lastChild: null
lastElementChild: null
localName: "button"
name: ""
namespaceURI: "http://www.w3.org/1999/xhtml"
nextElementSibling: null
nextSibling: null
nodeName: "BUTTON"
nodeType: 1
nodeValue: null
nonce: ""
offsetHeight: 0
offsetLeft: 0
offsetParent: null
offsetTop: 0
offsetWidth: 0
onabort: null
onanimationend: null
onanimationiteration: null
onanimationstart: null
onauxclick: null
onbeforecopy: null
onbeforecut: null
onbeforepaste: null
onbeforexrselect: null
onblur: null
oncancel: null
oncanplay: null
oncanplaythrough: null
onchange: null
onclick: null
onclose: null
oncontextmenu: null
oncopy: null
oncuechange: null
oncut: null
ondblclick: null
ondrag: null
ondragend: null
ondragenter: null
ondragleave: null
ondragover: null
ondragstart: null
ondrop: null
ondurationchange: null
onemptied: null
onended: null
onerror: null
onfocus: null
onformdata: null
onfullscreenchange: null
onfullscreenerror: null
ongotpointercapture: null
oninput: null
oninvalid: null
onkeydown: null
onkeypress: null
onkeyup: null
onload: null
onloadeddata: null
onloadedmetadata: null
onloadstart: null
onlostpointercapture: null
onmousedown: null
onmouseenter: null
onmouseleave: null
onmousemove: null
onmouseout: null
onmouseover: null
onmouseup: null
onmousewheel: null
onpaste: null
onpause: null
onplay: null
onplaying: null
onpointercancel: null
onpointerdown: null
onpointerenter: null
onpointerleave: null
onpointermove: null
onpointerout: null
onpointerover: null
onpointerrawupdate: null
onpointerup: null
onprogress: null
onratechange: null
onreset: null
onresize: null
onscroll: null
onsearch: null
onseeked: null
onseeking: null
onselect: null
onselectionchange: null
onselectstart: null
onstalled: null
onsubmit: null
onsuspend: null
ontimeupdate: null
ontoggle: null
ontransitionend: null
onvolumechange: null
onwaiting: null
onwebkitanimationend: null
onwebkitanimationiteration: null
onwebkitanimationstart: null
onwebkitfullscreenchange: null
onwebkitfullscreenerror: null
onwebkittransitionend: null
onwheel: null
outerHTML: "<button></button>"
outerText: ""
ownerDocument: document
parentElement: null
parentNode: null
part: DOMTokenList [value: ""]
prefix: null
previousElementSibling: null
previousSibling: null
scrollHeight: 0
scrollLeft: 0
scrollTop: 0
scrollWidth: 0
shadowRoot: null
slot: ""
spellcheck: true
style: CSSStyleDeclaration {alignContent: "", alignItems: "", alignSelf: "", alignmentBaseline: "", all: "", …}
tabIndex: 0
tagName: "BUTTON"
textContent: ""
title: ""
translate: true
type: "submit"
validationMessage: ""
validity: ValidityState {valueMissing: false, typeMismatch: false, patternMismatch: false, tooLong: false, tooShort: false, …}
value: ""
willValidate: true

Вы можете узнать больше о виртуальном DOM и React на https://indepth.dev/inside-fiber-in-depth-overview-of-the-new-reconciliation-algorithm-in-react/


-1

давайте разберемся в этом вопросе. React (или любая другая библиотека) - это «слой» на javascript.

Не существует такого понятия, как виртуальный дом, есть непривязанный дом.

позвольте мне объяснить простым javascript:

 let vDom = {};     // this is a object that will be used to hold the elements

 let d = document.createElement('div');
 d.innerHTML = 'hi, i am a new div';

 vDom['newDiv'] = d;

на этом этапе мы создали Div, который не отображается на dom, потому что он не прикреплен

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

как только мы вызываем: (например, добавляем его в тело)

    document.body.appendChild(vDom['newDiv'])

тогда мы это увидим;

 for one how saw javascript libs come and go , i suggest to any one 
 to do one simple thing : master JAVAscript, not layers :)

1
«Виртуального дома не существует» - Есть. Это ключевая особенность того, как работает React. Принятый ответ на этот вопрос хорошо это объясняет.
Квентин,

Ваш ответ на самом деле описывает настоящий DOM. Настоящая DOM существует после того, как вы вызываете document.createElement, независимо от того, был ли он добавлен.
Toffee Conmigo,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.