<!doctype html>
<html lang="en">
<head></head>
<body>
<ul class="list">
<li class="list__item">List item</li>
</ul>
</body>
</html>
HTML
└ head lang="en"
└ body
└ ul class="list"
└ li class="list__item"
└ List item
첫 번째 목록 항목의 내용을 수정하고 => List item one
두 번째 목록 항목도 추가하려고 한다고 가정해보자
이렇게 하려면 다음과 같이 해야한다.
const listItemOne = document.getElementsByClassName("list_item"")[0];
listItemOne.textContent = "List item one";
const list = document.getElementsByClassName("list")[0];
const listItemTwo = document.createElement("li");
listItemTwo.classList.add("list__item");
listItemTwo.textContent = "List item two";
list.appendChild(listItemTwo);
const list = document.getElementsByClassName("list")[0];
list.innerHTML = `
<li class="list__item">List item one</li>
<li class="list__item">List item two</li>
`
Virtual DOM은 DOM을 더 성능이 좋은 방식으로 자주 업데이트해야 하는 이러한 문제를 해결하기 위해 만들어짐
DOM이나 Shadow DOM과 달리 Virtual DOM은 공식 사양이 아니라 DOM과 인터페이스하는 새로운 방법
Virtual DOM은 원본 DOM의 복사본으로 생각할 수 있다
이 사본은 DOM API를 사용하지 않고도 자주 조작하고 업데이트 할 수 있다
가상 DOM에 대한 모든 업데이트가 이루어지면 원본 DOM에 어떤 특정 변경이 필요한지 살펴보고 목표에 맞게 최적화된 방식으로 변경할 수 있다
const virtualDOM = {
tagName: "html",
children: [
{ tagName: "head" },
{
tagName: "body",
children: [
{
tagName: "ul",
attributes: { "class" : "list" },
children: [
{
tagName: "li",
attributes: { "class": "list__item" },
textContent: "List item"
} // end li
]
} // end ul
]
} // end body
]
} // end html
이 객체를 가상 DOM으로 생각할 수 있다
원본 DOM과 마찬가지로 HTML 문서의 객체 기반 표현이다
그러나 그것은 평범한 자바스크립트 객체이기 때문에 필요할 때 까지 실제 DOM을 건드리지 않고도 자유롭고 자주 조작할 수 있다
전체 개체에 대해 하나의 개체를 사용하는 대신 가상 DOM의 작은 섹션으로 작업하는 것이 더 일반적이다
예를 들어 list순서가 지정되지 않은 목록 요소에 대응 하는 구성 요소에 대해 작업할 수 있다
const list = {
tagName: "ul",
attributes: { "class": "list" },
children: [
{
tagName: "li",
attributes: { "class": "list__item" },
textContent: "List item"
}
]
};
const copy = {
tagName: "ul",
attributes: { "class": "list" },
children: [
{
tagName: "li",
attributes: { "class": "list__item" },
textContent: "List item one"
},
{
tagName: "li",
attributes: { "class": "list__item" },
textContent: "List item two"
}
]
};
const diffs = [
{
newNode: { /* new version of list item one */ },
oldNode: { /* original version of list item one */ },
index: /* index of element in parent's list of child nodes */
},
{
newNode: { /* list item two */ },
index: { /* */ }
}
]
const domElement = document.getElementsByClassName("list")[0];
diffs.forEach((diff) => {
const newElement = document.createElement(diff.newNode.tagName);
/* Add attributes ... */
if (diff.oldNode) {
// If there is an old version, replace it with the new version
domElement.replaceChild(diff.newNode, diff.index);
} else {
// If no old version exists, create a new node
domElement.appendChild(diff.newNode);
}
})
import React from 'react';
import ReactDOM from 'react-dom';
const list = React.createElement("ul", { className: "list" },
React.createElement("li", { className: "list__item" }, "List item")
);
ReactDOM.render(list, document.body);
const newList = React.createElement("ul", { className: "list" },
React.createElement("li", { className: "list__item" }, "List item one"),
React.createElement("li", { className: "list__item" }, "List item two");
);
setTimeout(() => ReactDOM.render(newList, document.body), 5000);