source

Virtual DOM이란?

factcode 2022. 9. 15. 22:47
반응형

Virtual DOM이란?

최근에 페이스북의 리액트 프레임워크를 살펴보았습니다.'가상 DOM'이라는 개념을 사용하고 있는데잘 이해가 안 돼요

Virtual DOM이란?어떤 장점이 있습니까?

React는 DOM의 일부를 나타내는 커스텀오브젝트의 트리를 만듭니다.예를 들어 UL 요소를 포함하는 실제 DIV 요소를 작성하는 대신 React.ul 개체를 포함하는 React.div 개체를 만듭니다.실제로 실제 DOM을 누르거나 DOM API를 거치지 않고도 이러한 객체를 매우 빠르게 조작할 수 있습니다.그런 다음 컴포넌트를 렌더링할 때 이 가상 DOM을 사용하여 두 트리가 일치하도록 하기 위해 실제 DOM에서 무엇을 해야 하는지 파악합니다.

가상 DOM은 Blueprint처럼 생각할 수 있습니다.여기에는 DOM을 구축하는 데 필요한 모든 세부 사항이 포함되어 있지만 실제 DOM에 들어가는 모든 중량 부품이 필요하지 않기 때문에 훨씬 쉽게 만들고 변경할 수 있습니다.

예를 들어 매우 순진한 예를 들어보겠습니다.만약 당신의 집 안에 무언가 엉망진창이 있어서 그것을 청소해야 한다면, 당신의 첫 번째 단계는 무엇입니까?엉망진창인 방을 청소할 건가요, 아니면 온 집안을 청소할 건가요?대답은 청소가 필요한 방만 청소하는 것입니다.이것이 가상 DOM이 하는 일입니다.

일반 JS는 변경이 필요한 부분만 렌더링하는 대신 전체 DOM을 통과하거나 렌더링합니다.

마다, 처럼 다른 것을 .<div>DOMDOMDOM을 사용하다DOM 에서는, 이와 현재의 DOM 의 합니다. 다른이 부분)만 .<div>DOM dom dom dom dom dom dom dom dom 。

가상 DOM이란 무엇입니까?

가상 DOM은 페이지를 변경하기 전에 React 컴포넌트에 의해 생성된 실제 DOM 요소를 메모리 내에서 표현한 것입니다.

여기에 이미지 설명 입력

호출되는 렌더링 함수와 화면에 요소를 표시하는 단계입니다.

컴포넌트의 렌더 메서드는 마크업을 반환하지만 아직 최종 HTML은 아닙니다.이것은 실제 요소가 되는 것의 메모리 내 표현입니다(스텝 1단계입니다.그런 다음 출력은 브라우저에 표시되는 실제 HTML로 변환됩니다(스텝2).

그렇다면 가상 DOM을 생성하기 위해 이 모든 과정을 거쳐야 하는 이유는 무엇일까요?심플한 답변이것이 신속한 대응을 가능하게 하는 것입니다.이것은, 가상 DOM 의 확산에 의해서 행해집니다.2개의 가상 트리(오래된 트리와 새로운 트리)를 비교하여 필요한 변경만 실제 DOM에 적용합니다.

블로그 소개 #2 출처

A(VDOM)는 새로운 개념이 아닙니다.https://github.com/Matt-Esch/virtual-dom

VDOM은 전략적으로 DOM을 업데이트하기 위해 단일 페이지애플리케이션의 모든 노드를 재작성하지 않습니다.트리 구조에서 노드를 찾는 것은 쉽지만 SPA 앱용 DOM 트리는 엄청나게 커질 수 있습니다.이벤트 발생 시 노드 검색 및 업데이트는 시간 효율적이지 않습니다.

VDOM은 실제 돔의 높은 수준의 추상화를 생성하여 이 문제를 해결합니다.VDOM은 실제 DOM을 하이레벨의 경량 메모리트리 표현입니다

예를 들어 DOM에 노드를 추가하고 VDOM 복사본을 메모리에 보관하는 것을 고려합니다.

  1. 새 상태의 VDOM 생성
  2. 디피싱을 사용하여 오래된 VDOM과 비교합니다.
  3. 실제 DOM에서 다른 노드만 업데이트합니다.
  4. 새로운 VDOM을 오래된 VDOM으로 할당합니다.

모든 답이 훌륭합니다.제가 방금 생각해낸 비유는 아마도 실제 세계와 비슷할 겁니다.

진짜 DOM은 당신의 방과 같으며, 노드는 당신의 방에 있는 가구입니다.가상 DOM은 현재 룸의 청사진을 그리는 것과 같습니다.

누구나 가구를 옮겨본 경험이 있기 때문에 매우 피곤합니다(컴퓨터의 뷰를 갱신하는 것과 같은 개념).따라서 가구(노드)의 위치 변경/추가 작업을 원할 때는 꼭 필요한 변경만 하고 싶습니다.

그것을 달성하기 위한 구조 청사진은 나왔다.우리는 새로운 도면을 그리고 원래의 도면과 차이를 비교합니다.어떤 부품이 변경되었는지, 어떤 부품이 그대로 유지되는지 알 수 있습니다.그런 다음 실제 룸에 필요한 변경을 수행합니다(실제 DOM에서 변경된 노드를 업데이트합니다).만세!

(실제 DOM을 직접 비교하지 않고 가상 DOM에 의존해야 하는 이유는 무엇일까라고 생각할 수도 있습니다.음, 예를 들어 실제 DOM을 비교한다는 것은 다른 실제 방을 만들어 원래 방과 비교해야 한다는 것을 의미합니다.비용이 너무 많이 듭니다.)

다음은 ReactJ와 함께 자주 언급되는 Virtual DOM에 대한 간략한 설명과 반복입니다.

DOM(Document Object Model)은 구조화된 텍스트를 추상화한 것으로, HTML 코드와 cSS로 구성되어 있습니다.이러한 HTML 요소는 DOM의 노드가 됩니다.이전의 DOM 조작 방법에는 제한이 있습니다.Virtual DOM은 React가 생성되거나 사용되기 훨씬 전에 만들어진 문자 그대로의 HTML DOM의 추상화이지만, 우리의 목적을 위해 ReactJs와 함께 사용할 것입니다.Virtual DOM은 경량이며 브라우저의 DOM 구현에서 분리됩니다.Virtual DOM은 기본적으로 특정 시간에 DOM의 스크린샷(또는 복사)입니다.개발자의 관점에서 보면 DOM은 실가동 환경이고 Virtual DOM은 로컬(개발 환경)입니다.React 앱에서 데이터가 변경될 때마다 사용자 인터페이스의 새로운 Virtual DOM 표현이 생성됩니다.

ReactJs에서 정적 컴포넌트를 작성하기 위해 필요한 가장 기본적인 방법은 다음과 같습니다.

렌더 메서드에서 코드를 반환해야 합니다.JavaScript에서는 클래스가 예약된 단어이므로 모든 클래스를 className으로 변환해야 합니다.더 큰 변경 외에도 두 개의 DOM 간에는 사소한 차이가 있습니다.예를 들어 Virtual DOM에는 3개의 속성이 표시되지만 HTML DOM에는 표시되지 않습니다(키, ref 및 위험하게 SetInner).HTML).

Virtual DOM을 사용할 때 이해해야 할 중요한 점은 ReactElement와 ReactComponent의 차이입니다.

리액트 요소

  • ReactElement는 DOM 요소를 가볍고 상태 비저장적이며 불변의 가상 표현입니다.
  • ReactElement - 이것은 React의 주요 유형으로 Virtual 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'));

리액트 컴포넌트

  • React Component - React Component는 스테이트풀 컴포넌트입니다.
  • React.createClass는 ReactComponent로 간주됩니다.
  • 상태가 변경될 때마다 구성 요소가 다시 렌더링됩니다.

React Component의 상태가 변경될 때마다 가능한 한 HTML DOM을 변경하지 않고 React Component를 ReactElement로 변환하여 Virtual DOM에 삽입하여 빠르고 쉽게 비교 및 업데이트할 수 있도록 합니다.

React가 diff를 인식하면 하위 수준(HTML DOM) 코드로 변환되어 DOM에서 실행됩니다.

이것은 깔끔한 개념입니다.오류가 발생하기 쉽고 변동 가능한 상태에 의존하는 DOM을 직접 조작하는 대신 Virtual DOM이라는 값을 출력합니다.다음으로 Virtual DOM은 DOM의 현재 상태와 함께 확산됩니다.이것에 의해, 현재의 DOM 를 새로운 DOM 와 같이 보이게 하는, DOM 동작의 리스트가 생성됩니다.이러한 작업은 일괄적으로 신속하게 적용됩니다.

여기서부터 가져갑니다.

Virtual DOM은 상태 변화에 따라 노드의 하위 트리를 선택적으로 렌더링하는 HTML DOM의 추상화입니다.컴포넌트를 최신 상태로 유지하기 위해 가능한 한 DOM 조작을 최소한으로 억제합니다.

Virtual Dom은 돔의 복사본 1개를 만듭니다.Virtual dom은 dom과 비교되며 virtual dom은 dom의 변경된 부분만 업데이트합니다.돔 전체를 만드는 게 아니라 돔의 업데이트된 부분을 바꾼 거야시간이 많이 걸리고 이 기능을 통해 앱이 빠르게 작동합니다.

Virtual DOM은 브라우저 DOM 트리 구조의 일부 또는 전체 복사본입니다.React와 같은 프레임워크에 의해 생성되어 앱 코드를 통한 조작을 위해 메모리에 보관됩니다.

필요에 따라 가상 DOM은 앱 코드에 의해 브라우저의 DOM(실제로 사용자 인터페이스를 나타내는 DOM)을 업데이트하기 위해 사용됩니다.

또한 Virtual DOM은 단순한 디자인 패턴일 뿐이며 누구나 플레인 Javascript로 구현할 수 있습니다.

앱 상태 변경을 실제 DOM으로 푸시하기 전에 배치에 대응합니다.최신 가상 DOM 확산은 영향을 받는 모든 노드를 React에 제공합니다.다음으로 가상 DOM의 영향을 받는 노드는 조정이라고 불리는 매우 효율적인 프로세스에 의해 실제 DOM에 푸시됩니다.

아래 그림은 가상 DOM의 확산과 React의 실제 DOM과의 조화를 보여줍니다.


반응에서의 DOM 확산 및 조정 표시

자세한 내용은 여기를 참조해 주세요.가상 DOM 의 대응에 대해서는, 예를 참조해 주세요.

장점 - DOM 트리에서 노드를 추가, 삭제 또는 수정할 때 브라우저는 사용자 인터페이스를 앱 상태와 동기화하기 위해 계산을 수행하고 화면 레이아웃과 콘텐츠를 조정해야 합니다.데이터 및 이벤트의 연속 스트림을 볼 수 있는 매우 복잡하고 사후 대응적이며 대화형 애플리케이션에서는 DOM을 자주 업데이트해야 할 수 있습니다.

높은 빈도로 DOM을 업데이트(브라우저 화면 재도장)하는 것은 큰 문제이며, 이것이 React js의 Virtual DOM이 복구되는 이유입니다.

리액트의 구조 단위는 구성요소입니다.각 컴포넌트에는 상태가 있습니다.구성 요소의 상태가 변경될 때마다 React는 V-DOM 트리를 수정합니다.이후 V-DOM의 최신 버전을 이전 버전의 V-DOM과 비교합니다. 이 계산(확산) 후 React는 변경된 V-DOM 개체를 인식하면 R-DOM의 해당 개체만 수정합니다.

평신도로 말하면

DOM에 div 요소를 추가했다고 가정하면 React는 전체 R-DOM을 변경하지 않고 V-DOM 복사본을 만듭니다.새로 생성된 이 V-DOM은 이전 V-DOM과 비교됩니다. 실제 DOM에서 서로 다른 노드만 업데이트합니다.이제 새로 생성된 V-DOM은 향후 V-DOM의 이전 버전으로 간주됩니다.

추신 1. 일반 js와 달리 V-DOM의 새로운 버전이 모두 생성되고 R-DOM이 부분적으로 업데이트됩니다. 2. React는 상태의 모든 변화를 업데이트하지 않고 R-DOM에 대한 업데이트가 일괄적으로 전송됩니다.

React 문서에 따르면 https://reactjs.org/docs/faq-internals.html#what-is-the-virtual-dom

React world에서 "가상 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
       )
   }
}

반환 내의 코드는 실제로는 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-dev/inside-fiber-in-depth-of-the-reconsion-algorithm-in-react/참조하십시오.

React는 메모리 내에 실제 DOM을 경량화한 상태로 유지합니다.이것은 가상 DOM이라고 불립니다.오브젝트 상태가 변경되면 가상 DOM은 모든 오브젝트를 갱신하지 않고 실제 DOM 내의 오브젝트만 변경합니다.

이 문제에 대해 질서정연하고 이치에 맞도록 합시다.리액트(또는 다른 라이브러리)는 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를 만들었습니다. 왜냐하면 그것이 부착되지 않았기 때문입니다.

액세스, 속성 추가, 값 추가, 변경 등이 가능합니다.

(예를 들어, 본문에 추가)를 호출합니다.

    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 :)

언급URL : https://stackoverflow.com/questions/21965738/what-is-virtual-dom

반응형