Недавно я посмотрел на фреймворк Facebook React . Он использует концепцию под названием «виртуальный DOM», которую я не совсем понял.
Что такое виртуальный DOM? Каковы преимущества?
javascript
reactjs
Физер Хан
источник
источник
Ответы:
React создает дерево настраиваемых объектов, представляющих часть DOM. Например, вместо создания фактического элемента DIV, содержащего элемент UL, он создает объект React.div, содержащий объект React.ul. Он может очень быстро манипулировать этими объектами, фактически не касаясь реальной DOM или проходя через DOM API. Затем, когда он отображает компонент, он использует эту виртуальную DOM, чтобы выяснить, что ему нужно делать с реальной DOM, чтобы два дерева совпали.
Вы можете думать о виртуальном DOM как о чертеже. Он содержит все детали, необходимые для построения DOM, но поскольку он не требует всех тяжелых частей, которые входят в реальный DOM, его можно создавать и изменять гораздо проще.
источник
virtual dom
, но в нем нет ничего вычурного и преувеличенного.Возьмем пример, хотя и очень наивный: если у вас что-то пошло не так в комнате вашего дома, и вам нужно ее убрать, что будет вашим первым шагом? Будете ли вы убирать свою комнату или весь дом? Ответ: вы будете убирать только ту комнату, которая требует уборки. Это то, что делает виртуальный DOM.
Обычный JS просматривает или отображает всю DOM вместо визуализации только той части, которая требует изменений.
Поэтому всякий раз, когда у вас есть какие-либо изменения, например, вы хотите добавить еще один
<div>
в свою DOM, будет создана виртуальная DOM, которая фактически не вносит никаких изменений в фактическую DOM. Теперь с этим виртуальным DOM вы будете проверять разницу между этим и вашим текущим DOM. И только другая часть (в данном случае новая<div>
) будет добавлена вместо повторного рендеринга всей DOM.источник
Что такое виртуальный DOM?
Виртуальный DOM - это представление в памяти реальных элементов DOM, сгенерированных компонентами React до того, как на странице будут внесены какие-либо изменения.
Это шаг, который происходит между вызываемой функцией рендеринга и отображением элементов на экране.
Метод рендеринга компонента возвращает некоторую разметку, но это еще не окончательный HTML. Это представление в памяти того, что станет реальными элементами (это шаг 1). Затем этот вывод будет преобразован в настоящий HTML, который отображается в браузере (это шаг 2).
Так зачем же проходить через все это для создания виртуальной модели DOM? Простой ответ - это то, что позволяет быстро реагировать. Он делает это посредством виртуального различения DOM. Сравнение двух виртуальных деревьев - старого и нового - и внесение только необходимых изменений в реальный DOM.
Источник из Intro To React # 2
источник
virtual DOM
(VDOM) не является новой концепцией: https://github.com/Matt-Esch/virtual-dom .Стратегия VDOM заключается в обновлении DOM без перерисовки всех узлов в одностраничном приложении. Найти узел в древовидной структуре просто, но дерево DOM для приложения SPA может быть огромным. Поиск и обновление узла / узлов в случае события неэффективно по времени.
VDOM решает эту проблему, создавая абстракцию высокого уровня реального dom. VDOM - это легкое дерево высокого уровня, представляющее реальную модель DOM в памяти.
Например, рассмотрите возможность добавления узла в DOM; реагировать сохранить копию VDOM в памяти
источник
Это краткое описание и повторение виртуального 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
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 имеет изменение состояния, нам нужно как можно меньше изменений в HTML DOM, чтобы ReactComponent был преобразован в ReactElement, который затем можно было вставить в виртуальную DOM, быстро и легко сравнить и обновить.
Когда React знает разницу - он конвертируется в код низкого уровня (HTML DOM), который выполняется в DOM.
источник
Это изящная концепция: вместо того, чтобы напрямую манипулировать DOM, который подвержен ошибкам и полагается на изменяемое состояние, вы вместо этого выводите значение, называемое Virtual DOM. Virtual DOM затем сравнить при с текущим состоянием DOM, который генерирует список операций DOM , которые сделали бы текущий вид DOM , как новый. Эти операции применяются быстро в пакетном режиме.
Взято отсюда.
источник
Виртуальная модель DOM - это абстракция модели HTML DOM, которая выборочно отображает поддеревья узлов на основе изменений состояния. Он выполняет наименьшее количество манипуляций с DOM, чтобы поддерживать ваши компоненты в актуальном состоянии.
источник
Виртуальный Дом создается одной копией Дом. Виртуальный дом сравнивается с домом, а виртуальный дом обновляет только ту часть, которая изменилась. он не отображает весь дом, а просто изменил обновленную часть дома в домике. Это занимает очень много времени, и благодаря этой функции наше приложение работает быстро.
источник
Все ответы прекрасны. Я просто привел аналогию, которая, вероятно, может дать метафору из реального мира.
Настоящая модель DOM похожа на вашу комнату, а узлы - это мебель в вашей комнате. Виртуальный DOM подобен тому, как мы рисуем план этой текущей комнаты.
У всех нас есть опыт перемещения мебели, это очень утомительно (та же концепция, что и обновление представлений в компьютерах). Таким образом, всякий раз, когда мы хотим изменить положение / добавить мебель (узлы), мы хотим внести только очень необходимые изменения.
Blueprint пришел на помощь, чтобы достичь этого. Рисуем новый чертеж и сравниваем разницу с исходным. Это позволяет нам узнать, какая часть была изменена, а какая осталась прежней. Затем мы вносим необходимые изменения в реальную комнату (обновляем измененные узлы в реальной DOM). Ура.
(Кто-то может подумать, почему мы должны полагаться на виртуальную, а не напрямую сравнивать реальную DOM? Ну, по аналогии, сравнение реальной DOM означает, что вам нужно создать еще одну реальную комнату и сравнить ее с исходной . Это слишком дорого.)
источник
Структурной единицей 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 отправляются пакетами.
источник
Согласно документу 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/
источник
давайте разберемся в этом вопросе. 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 :)
источник