什么是虚拟 DOM?(让我们来构建它!)
你可能听说过虚拟 DOM(以及影子 DOM)。你甚至可能使用过它(JSX 本质上就是 VDOM 的语法糖)。如果你想了解更多,那么来对地方了!
在本教程中,我将向您展示什么是虚拟 DOM,并且(可能在本系列的下一篇中)向您展示如何实现我们自己的虚拟 DOM。那就开始吧!
什么是虚拟 DOM?
DOM 操作确实很繁重。如果只进行一次,差异可能看起来很小(给对象赋值属性大约需要 0.4 毫秒),但随着时间的推移,差异会逐渐增大。
// Assigning a property to an object 1000 times
let obj = {};
console.time("obj");
for (let i = 0; i < 1000; i++) {
obj[i] = i;
}
console.timeEnd("obj");
// Manipulating dom 1000 times
console.time("dom");
for (let i = 0; i < 1000; i++) {
document.querySelector(".some-element").innerHTML += i;
}
console.timeEnd("dom");
当我运行上面的代码片段时,我发现第一个循环大约花费~3ms,而第二个循环花费~41ms。
现在让我们举一个现实生活中的例子。
function generateList(list) {
let ul = document.createElement('ul');
document.getElementByClassName('.fruits').appendChild(ul);
fruits.forEach(function (item) {
let li = document.createElement('li');
ul.appendChild(li);
li.innerHTML += item;
});
return ul;
}
document.querySelector("ul.some-selector").innerHTML = generateList(["Banana", "Apple", "Orange"])
到目前为止一切顺利。现在,如果数组发生变化,我们需要重新渲染,我们会这样做:
document.querySelector("ul.some-selector").innerHTML = generateList(["Banana", "Apple", "Mango"])
看看出了什么问题?
即使只有一个元素需要改变,我们也会因为懒惰而改变整个事物
这就是创建虚拟 DOM 的原因。
我知道你已经等待很久了,所以让我们进入正题。
什么是虚拟 DOM?
虚拟 DOM 是 DOM 作为对象的表示。因此,假设你有以下 HTML:
<div class="contents">
<p>Text here</p>
<p>Some other <b>Bold</b> content</p>
</div>
它可以写成以下 VDOM 对象:
let vdom = {
tag: "div",
props: { class: 'contents' },
children: [
{
tag: "p",
children: "Text here"
},
{
tag: "p",
children: ["Some other ", { tag: "b", children: "Bold" }, " content"]
}
]
}
请注意,现实生活中可能存在更多属性,这是一个简化版本。
我确信这是不言自明的,特别是如果你用过 React。如果没有的话:
- VDOM 基本上是一个对象,
- 属性称为
tag
(有时也称为type
),基本上是标签的名称 props
包含所有 props 的属性children
名为的属性- 如果内容只是文本,则为字符串
- 如果内容包含元素,则为 VDOM 数组
- 属性称为
我们像这样使用 VDOM:
- 我们对 VDOM 进行更改,而不是 DOM
- 函数检查 DOM 和 VDOM 之间的所有差异,并仅更改真正改变的内容
- 刚刚用于更改内容的 VDOM 被标记为最新更改,以便我们下次可以比较 VDOM,从而节省更多
有什么好处?
我确信你现在已经明白了,但这里有一个实际的例子。让我们以之前的generateList
函数为例,并对其进行改进:
function generateList(list) {
// VDOM generating stuff which I will explain later...
}
patch(oldUL, generateList(["Banana", "Apple", "Orange"]));
不要介意补丁功能,它基本上将更改附加到 DOM。
现在,当我们将来再次更改 DOM 时:
patch(oldUL, generateList(["Banana", "Apple", "Mango"]));
patch 函数发现只有第三个li
发生了变化,并且只有第三个li
发生了变化,而不是改变所有三个元素
这就是 VDOM 的全部内容,下一部分我将向您展示如何实现 VDOM
文章来源:https://dev.to/siddharthshyniben/what-is-the-virtual-dom-let-s-build-it-5070