德鲁:对于我们这些不熟悉的人来说,当你说像 Preact 放弃虚拟 DOM 并使一切变得更小这样的东西时,虚拟 DOM 给我们带来了什么?
克里斯:为了回答这个问题,我想稍微退一步。框架和其他基于状态的库为您提供的最好的东西之一就是 DOM diffing。如果您并没有真正更新 UI 太多,您可以这样说:“这是标记应该是什么样子的字符串。在 HTML 中,我将把所有这些标记放在这个元素中。” 当你需要改变某件事时,你会再做一次。这对于浏览器来说有点昂贵,因为它会触发重绘。
克里斯:任何有价值的基于状态的 UI 事物都将实现一些 DOM 比较,他们说,“这就是 UI 应该是什么样子的。这是 DOM 中现在的样子。有什么不同?它将去改变这些事情。它实际上正在做您自己手动更新 UI 所需要做的事情,但它是在幕后为您做的。所以你可以说,“这就是我想要的样子。” 然后库或框架就会解决这个问题。
克里斯:像 Preact 或 Alpine 这样的小东西,他们实际上是直接这样做的。他们将您提供给他们的 UI 外观字符串转换为 HTML 元素。然后他们将每个元素与文本 DOM 中相应的部分进行比较。当你最终得到的 UI 变得越来越大时,这可能会对性能产生影响,因为一遍又一遍地查询 DOM 会变得昂贵。如果您想了解出现问题的界面类型,请右键单击并检查 Twitter 上“收藏夹”按钮或 Facebook 上“喜欢”按钮上的元素。看看 div 的嵌套,让您到达该元素。这是非常非常深的。它就像十几个左右的 div,一个嵌套在另一个 div 中,只是为了那一条推文。
克里斯:当你开始深入这么多层时,它开始真正影响性能。虚拟 DOM 所做的不是每次都检查真实 DOM,而是创建一个基于对象的 UI 在 JavaScript 中的映射。然后对您想要替换现有 UI 的 UI 执行相同的操作,并比较这两个 UI。从理论上讲,这比在真实 DOM 中实现的性能要高得多。一旦它获得了需要更改的内容的列表,它就会开始执行这些更改。但它只需要攻击 DOM 一次。它并不是每次都检查每一个元素。如果您有 Twitter、Facebook、QuickBooks 或类似的界面,那么虚拟 DOM 可能很有意义。