Javascript 为什么我们需要虚拟DOM?
我读了这篇文章 这里有一个代码示例,示例必须帮助我们理解这个问题的答案——“为什么我们需要虚拟DOM?” 第条: 例如:假设我们要从数组中呈现列表。我们可以像下面这样做 现在,如果列表发生更改,可以再次调用上述方法来生成列表 在上面的代码中,会生成一个新列表,并在文档中进行设置。这种方法的问题是只更改了单个水果的文本,但生成了一个新列表并更新为DOM。这个操作在DOM中很慢。我们可以更改未优化的代码,如下所示。这将减少DOM中的操作数 未优化和优化代码的最终结果相同,但未优化DOM操作的代价是性能。如果列表的大小很大,那么您可以看到差异。这就是我们在像主干js这样的旧框架中遇到的问题 那么,我们为什么需要虚拟DOM呢?就是要解决上述问题 像react这样的现代框架所做的是,每当状态/道具中发生变化时,就会创建一个新的虚拟DOM表示,并将其与以前的表示进行比较。在我们的例子中,唯一的变化将是“苹果”变成“菠萝”。由于只更改文本而不是替换整个列表,因此react将使用以下代码更新DOM 好的,我理解虚拟DOM的用途- 通过使用虚拟DOM,我们可以发现发生了什么变化,并且通过这种变化,我们可以只将这些变化应用于真实DOM,而不是替换整个DOM 但是,是什么阻止我们在不使用虚拟DOM的情况下编写这篇文章呢Javascript 为什么我们需要虚拟DOM?,javascript,virtual-dom,Javascript,Virtual Dom,我读了这篇文章 这里有一个代码示例,示例必须帮助我们理解这个问题的答案——“为什么我们需要虚拟DOM?” 第条: 例如:假设我们要从数组中呈现列表。我们可以像下面这样做 现在,如果列表发生更改,可以再次调用上述方法来生成列表 在上面的代码中,会生成一个新列表,并在文档中进行设置。这种方法的问题是只更改了单个水果的文本,但生成了一个新列表并更新为DOM。这个操作在DOM中很慢。我们可以更改未优化的代码,如下所示。这将减少DOM中的操作数 未优化和优化代码的最终结果相同,但未优化DOM操作的代价是性
document.querySelector('li').innerText = fruits[0]
document.querySelector('li').innerText = fruits[0]
但是,是什么阻止我们在不使用虚拟DOM的情况下编写这篇文章呢
document.querySelector('li').innerText = fruits[0]
document.querySelector('li').innerText = fruits[0]
这跳过了您正在计算的部分:
- 数组中的第一个项(仅第一个项)已更改
- 当数组中的项发生变化时,列表的内容也会发生变化
- 第一个项目映射到第一个li项目
您可以自己编写代码,但这需要大量的开发时间。目前有两种主要的框架/库样式呈现方法: 虚拟Dom 其中,库(如React)计算渲染的DOM在虚拟DOM中的外观,然后将其与实际DOM进行比较并更新差异 当事件发生时(当前处于React中),它们会转化为合成事件,从
窗口
(可能是我正在编写的文档),然后React将它们映射到使用效果
更新数据的适当函数,触发虚拟DOM的组件部分的重新呈现-与真实DOM进行区分和同步
多姆
其中,库(如Angular)使用围绕自定义元素创建的类来管理实际更新DOM所需的数据,然后在生命周期的各个点更新该自定义元素中的DOM
当事件发生时,它们从创建事件的元素中被调度,如果需要,它们可以冒泡,但是大多数情况下,它们会被自定义元素的类捕获,以触发自定义元素上的自定义事件,或者管理状态/数据,而由于生命周期的原因,这些状态/数据又会与DOM同步
虽然目前单独使用自定义元素的成本稍高,但一旦连接了阴影DOM
,性能问题将从渲染转移到自定义开发人员代码或浏览器如何处理阴影DOM
每个人都有自己喜欢的理由,当执行服务器端渲染时,虚拟DOM会更容易,基于DOM的方法更符合web标准并利用浏览器。第一个示例完全错误generateList
返回HTMLElement,而不是字符串。您不能执行x.innerHTML=someHTMLElement
。关于您的问题“但是是什么阻止了我们在不使用虚拟DOM的情况下编写本文?”没有什么阻止您这样做。但是使用虚拟DOM,您可以首先检查该值是否需要更改,而不是无论如何都要更改,从长远来看,这样做成本更高是的,示例是错误的。但我们可以解决它。例如,我们可以使用x.innerHtml=''和x.appendChild,或者类似的东西谢谢。我认为第一个示例-(document.getElementById('#list').innerHtml=generateList(fruits))-只解决列表中的第三个任务,但不解决第一个和第二个任务。第二个“简单”示例(document.querySelector('li').innerText=fruits[0])只解决第一个任务。虚拟dom解决所有任务
document.querySelector('li').innerText = fruits[0]
document.querySelector('li').innerText = fruits[0]