首页 文章

为什么React的Virtual DOM概念被认为比脏模型检查更具性能?

提问于
浏览
334

我在http://www.youtube.com/watch?v=x7cQ3mrcKaY看到一个React dev谈话,并且发言者提到模型的脏检查可能很慢 . 但是,由于虚拟DOM在大多数情况下应该大于模型,因此不计算虚拟DOM之间的差异实际上甚至更低性能吗?

我非常喜欢Virtual DOM的潜在力量(特别是服务器端渲染),但我想知道所有的优点和缺点 .

5 回答

  • 70

    Virtual Dom不是由反应发明的 . 它是HTML dom的一部分 . 它是轻量级的,与特定于浏览器的实现细节分离 .

    我们可以将虚拟DOM视为React的HTML DOM的本地和简化副本 . 它允许React在这个抽象的世界中进行计算,并跳过“真正的”DOM操作,通常是缓慢的,特定于浏览器的 . 实际上,DOM和VIRTUAL DOM之间没有很大的区别 .

    以下是使用Virtual Dom的原因(来源https://hackernoon.com/virtual-dom-in-reactjs-43a3fdb1d130):

    当你这样做:document.getElementById('elementId') . innerHTML =“新值”以下事情发生:
    浏览器需要解析HTML它删除了elementId的子元素用新值更新DOM值重新计算父级和子级的css更新布局,即每个元素在屏幕上精确坐标遍历渲染树并绘制它在浏览器显示上重新计算CSS和更改的布局使用复杂的算法,它们会影响性能 .

    以及更新DOM属性,即 . 值 . 它遵循一种算法 .

    现在,假设您直接更新DOM 10次,那么上述所有步骤将逐个运行,更新DOM算法需要时间来更新DOM值 .

    这就是Real DOM比虚拟DOM慢的原因 .

  • 34

    我是virtual-dom模块的主要作者,所以我或许可以回答你的问题 . 事实上,这里有两个问题需要解决

    • When do I re-render? 答:当我发现数据很脏时 .

    • How do I re-render efficiently? 答案:使用虚拟DOM生成真正的DOM补丁

    在React中,每个组件都有一个状态 . 这种状态就像你可能在淘汰赛或其他MVVM风格的库中找到的一个可观察的状态 . 从本质上讲,React知道 when 重新渲染场景,因为它能够观察到这个数据何时发生变化 . 脏检查比可观察的慢,因为您必须定期轮询数据并以递归方式检查数据结构中的所有值 . 相比之下,在状态上设置值将向侦听器发出某个状态已更改的信号,因此React可以简单地侦听状态上的更改事件并排队重新呈现 .

    虚拟DOM用于有效地重新呈现DOM . 这并不是因为计算两个虚拟树之间的差异有一些开销,但虚拟DOM差异是要了解DOM中需要更新的内容,而不是数据是否已更改 . 实际上, the diff algorithm is a dirty checker itself 但它用于查看DOM是否是脏的 .

    我们的目标是仅在状态发生变化时重新渲染虚拟树 . 因此,使用observable检查状态是否已更改是防止不必要的重新渲染的有效方法,这会导致大量不必要的树差异 . 如果什么都没有改变,我们什么都不做 .

    虚拟DOM很不错,因为它让我们编写代码就好像我们重新渲染整个场景一样 . 在幕后我们想要计算一个补丁操作,它可以更新DOM,看看我们的期望 . 因此,虽然虚拟DOM差异/补丁算法 is probably not the optimal solution ,它为我们提供了一种非常好的方式来表达我们的应用程序 . 我们只是声明我们想要的东西,React / virtual-dom将解决如何让你的场景看起来像这样 . 我们不必重新渲染整个场景,这可能比修补它的效率低得多 .

  • -1

    以下是React团队成员SebastianMarkbåge发表的评论,其中阐述了一些观点:

    React对输出进行区分(这是一种已知的可序列化格式,DOM属性) . 这意味着源数据可以是任何格式 . 它可以是不可变的数据结构和闭包内的状态 . Angular模型不保留引用透明度,因此本质上是可变的 . 您改变现有模型以跟踪更改 . 如果您的数据源每次都是不可变数据或新数据结构(例如JSON响应),该怎么办?脏检查和Object.observe对闭包范围状态不起作用 . 这两件事显然对功能模式非常有限 . 此外,当您的模型复杂性增加时,进行脏跟踪变得越来越昂贵 . 但是,如果你只在视觉树上进行差异化,比如React,那么它就不会增长太多,因为你能够在任何给定点在屏幕上显示的数据量受到UI的限制 . Pete上面的链接涵盖了更多的性能优势 .

    https://news.ycombinator.com/item?id=6937668

  • 459

    我非常喜欢Virtual DOM的潜在力量(特别是服务器端渲染)但我想知道所有的利弊 . - OP

    React不是唯一的DOM操作库 . 我鼓励您通过阅读article from Auth0来了解其他选择,其中包括详细的解释和基准 . 你会问:我会在这里强调一下它们的优点和缺点:

    React.js'虚拟DOM PROS快速高效的“差异化”算法多个前端(JSX,hyperscript)轻量级足以在移动设备上运行很多牵引力和思想共享可以在没有React的情况下使用(即作为独立引擎)CONS Full in- DOM的内存副本(更高的内存使用)静态和动态元素之间没有区别Ember.js'Glimmer PROS快速高效的差异算法静态和动态元素之间的区别与Ember的API 100%兼容(无需对主要内容进行重大更新即可获得优势现有代码)DOM CONS Meant的轻量级内存表示仅在Ember中使用只有一个前端可用增量DOM PROS减少内存使用简单API轻松集成许多前端和框架(从一开始就意味着模板引擎后端)CONS没有其他库那么快(这是有争议的,请参阅下面的基准)减少思想共享和社区使用

  • 122

    我最近在这里阅读了一篇关于React的diff算法的详细文章:http://calendar.perfplanet.com/2013/diff/ . 根据我的理解,React的快速之处在于:

    • 批量DOM读/写操作 .

    • 仅对子树进行高效更新 .

    与脏检查相比,IMO的主要区别是:

    • Model dirty-checking :每当调用 setState 时,React组件都显式设置为脏,因此这里不需要比较(数据) . 对于脏检查,(每个模型的)比较总是发生在每个摘要循环中 .

    • DOM updating :DOM操作非常昂贵,因为修改DOM也会应用和计算CSS样式,布局 . 从不必要的DOM修改中节省的时间可能比传播虚拟DOM所花费的时间长 .

    第二点对于非平凡模型更为重要,例如具有大量字段或大列表的模型 . 复杂模型的一个字段更改将仅导致涉及该字段的DOM元素所需的操作,而不是整个视图/模板 .

相关问题