译文: Virtual DOM is pure overhead

date
Aug 10, 2019
slug
virtual-dom-is-pure-overhead-translate
status
Published
tags
Javascript
Vuejs
Reactjs
summary
type
Post
本文为译文,原文为:
如果您在最近几年中使用过JavaScript框架,那么您可能已经听说过“虚拟DOM很快”这一短语,通常被说来意味着它比真实DOM快。这是一个令人惊讶的前端技术概念。例如,人们问Svelte在不使用虚拟DOM时如何更快。(作者在反讽🤔)
是时候让我们仔细揣摩揣摩了。

什么是虚拟 dom ?

在许多框架中,你可以通过 render 来构建一个应用,下面用 react 来当作示例:
function HelloMessage(props) {
  return (
    <div className="greeting">
      Hello {props.name}
    </div>
  );
}
你也可以不使用 jsx 来完成:
function HelloMessage(props) {
  return React.createElement(
    'div',
    { className: 'greeting' },
    'Hello ',
    props.name
  );
}
结果是相同的,在这其中有一个对象会向我们展示当前的页面长什么样,而这个对象就是虚拟DOM。每一次你的应用中的状态更新(例如:name),框架都会创建一个新的状态。框架的任务就是将新状态与旧状态仔细对比,找到变化并将他们输出为真实的DOM。

虚拟 dom 更快这个概念是怎么开始的?

关于虚拟DOM性能的误解可追溯到React的发布。在反思最佳实践开创性的2013通话由原阵营的核心团队成员皮特·亨特,我们学到以下知识点:
这实际上是非常快的,主要是因为大多数DOM操作往往很慢。DOM上有很多性能工作,但是大多数DOM操作往往会丢帧。
但是等一下!如果将其与效率较低的框架比较那肯定是快的。与其如此,不如这样:
onEveryStateChange(() => {
  document.body.innerHTML = renderMyApp();
});
(疯狂吐槽 🤔 ,总结一下作者认为虚拟DOM的快可以用上述代码概括,那就是状态变化,将重新编译好的jsx完全赋值给 innerHTML ...)
皮特在不久后澄清...
React 并不是魔术,就像将 c 写入汇编后击败 c 编译器一样。你也可以在你需要的情况下使用原生DOM和 API 进行操作从而击败 react。使用C或Java或JavaScript可以将性能提高一个数量级,因此您不必在意平台的细节。使用 react 你甚至可以不考虑性能而构建应用,因为它默认是快速的。
...但这个解释我并不买账

因此虚拟DOM是慢的么?

也不能这么说。只能说 虚拟DOM在通常情况下足够快 ,但有一些注意事项。
React 最初的承诺是当你修改状态重新渲染整个应用时不用担心性能。我认为这并不正确,如果真如此,那为什么还会提供shouldComponentUpdate这样的函数还跳过对组件的更新。
即使有了shouldComponentUpdate,一次完成更新整个应用程序的虚拟DOM的工作量仍然很大。不久前,React团队推出了一种叫做React Fiber的东西,它可以将更新分成较小的块。这意味着(除其他事项外)更新不会长时间阻塞主线程,尽管它不会减少工作总量或更新所花费的时间。

开销在哪里?

重点在于 diff 。您必须先将新的虚拟DOM与先前的快照进行比较,然后才能对真实DOM应用更改。以前面的HelloMessage 示例为例,假设 name 从 world 改为 everybody。
  1. 两个快照都包含一个元素。在两种情况下都是 <div> ,这意味着我们可以保留相同的DOM节点
  1. 我们列举了新旧属性上的所有属性, <div> 以查看是否需要更改,添加或删除任何属性。在这两种情况下,我们都有一个属性 className 的值为"greeting"
  1. 到元素中,我们看到文本已更改,因此我们需要更新真实的DOM。
在这三步中,只有第3步对于 DOM 是有影响的。而这些都可以用下面这个代码代替:
if (changed.name) {
  text.data = name;
}
(这几乎完全是Svelte生成的更新代码。与传统的UI框架不同,Svelte是一个编译器,它在构建时就知道应用程序中的情况如何发生变化,而不必等着在运行时进行工作。)

为什么框架要使用虚拟DOM?

重要的是要了解虚拟DOM不是功能。这是达到目的的一种手段,最终是声明性的,状态驱动的UI开发。虚拟DOM非常有价值,因为它使您无需考虑状态转换即可构建应用程序,并且性能通常足够好。这意味着更少的错误代码,而将更多的时间花费在创造性的任务上,而不是乏味的工作上。
但事实证明,我们无需使用虚拟DOM就可以实现类似的编程模型-这就是Svelte的用武之地。

总结

  1. 虚拟DOM不是功能。这是达到目的的一种手段
  1. 场景不同需求不同

© i7eo 2017 - 2022