问题描述
我阅读了文章https://dev.to/karthikraja34/what-is-virtual-dom-and-why-is-it-faster-14p9
有代码示例,示例必须帮助我们理解问题的答案——“为什么我们需要虚拟 DOM?”
来自文章:
例如:假设我们要从数组渲染列表。我们可以像下面那样做。
function generateList(fruits) {
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
}
let fruits = ['Apple','Orange','Banana']
document.getElementById('#list').innerHtml = generateList(fruits)
fruits = ['Pineapple','Banana']
document.getElementById('#list').innerHtml = generateList(fruits)
在上面的代码中,生成了一个新的列表,并在文档中进行了设置。这种方法的问题是只更改了单个水果的文本,但会生成一个新列表并将其更新为 DOM。此操作在 DOM 中很慢。我们可以像下面这样更改未优化的代码。这将减少 DOM 中的操作次数。
document.querySelector('li').innerText = fruits[0]
未优化和优化代码的最终结果相同,但未优化 DOM 操作的成本是性能。如果列表的大小很大,那么您可以看到差异。这是我们在主干 js 等旧框架中遇到的问题。
那么回答我们的大问题为什么我们需要虚拟 DOM?就是为了解决上面的问题。
像 React 这样的现代框架所做的是,每当 state/props 中的某些内容发生变化时,就会创建一个新的虚拟 DOM 表示,并将其与前一个进行比较。在我们的示例中,唯一的变化将是“Apple”到“Pineapple”。由于仅更改文本而不是替换整个列表,因此 react 将通过以下代码更新 DOM。
document.querySelector('li').innerText = "Pineapple"
好的,我理解虚拟 DOM 的目的 -
通过使用虚拟 DOM,我们可以找出更改的内容,然后我们可以仅将这些更改应用于真实 DOM,而不是替换整个 DOM
但是是什么阻止我们在不使用虚拟 DOM 的情况下编写它?
document.querySelector('li').innerText = fruits[0]
解决方法
但是是什么阻止我们在不使用虚拟 DOM 的情况下编写它?
document.querySelector('li').innerText = fruits[0]
这会跳过您正在解决的部分:
- 数组中的第一项,并且只有第一项发生了变化
- 当数组中的项目发生变化时,列表的内容也会发生变化
- 第一个项目映射到第一个 li 项目
根据您的数据生成虚拟 DOM,然后应用差异会完成这些步骤。
您可以自己编写代码来完成这项工作,但这需要大量的开发时间。
,目前有两种主要的框架/库风格渲染方法:
虚拟 Dom
其中一个库(例如 React)计算渲染的 DOM 在 Virtual Dom 中应该是什么样子,然后将其与实际 DOM 进行比较并更新差异。
当事件发生时(当前在 React 中),它们会变成从 document.getElementById("fmm-payment-btn").onclick = function()
分派的合成事件(现在我正在编写它可能是文档),然后 React 将它们映射到使用 {{1 }} 来更新数据,触发虚拟 DOM 组件部分的重新渲染 - 与真实 DOM 进行差异化和同步。
DOM
其中的库(例如 Angular)使用围绕自定义元素创建的 window
来管理实际更新 DOM 所需的数据,然后在生命周期的各个点更新该自定义元素中的 DOM。
当事件发生时,它们从创建事件的元素中分派,如果需要可以冒泡,但大多数情况下它们会被自定义元素的类捕获以触发自定义元素上的自定义事件,或管理状态/数据 -由于生命周期,这反过来又与 DOM 同步。
虽然现在单独使用自定义元素的成本略高,但是一旦连接了 effects
,性能问题就会从渲染转移到自定义开发者代码或浏览器如何处理 Shadow DOM。
每个人都有自己喜欢的理由,虚拟 DOM 在执行服务器端渲染时会更容易,其中基于 DOM 的方法更符合网络标准并利用浏览器。