百摩网
当前位置: 首页 生活百科

dom的几种常见节点(虚拟DOM真的比操作原生DOM快吗)

时间:2023-07-13 作者: 小编 阅读量: 1 栏目名: 生活百科

出于可维护性的考虑,这显然不可能。MVVM的变化检查是数据层面的,而React的检查是DOM结构层面的。VirtualDOM、脏检查MVVM、数据收集MVVM在不同场合各有不同的表现和不同的优化需求。主流的框架合理的优化,足以应对绝大部分应用的性能需求。

尤雨溪:https://www.zhihu.com/question/31809713/answer/53544875

Virtual DOM 真的比操作原生 DOM 快吗?

1. 原生 DOM 操作 vs. 通过框架封装操作。

这是一个性能 vs. 可维护性的取舍。框架的意义在于为你掩盖底层的 DOM 操作,让你用更声明式的方式来描述你的目的,从而让你的代码更容易维护。没有任何框架可以比纯手动的优化 DOM 操作更快,因为框架的 DOM 操作层需要应对任何上层 API 可能产生的操作,它的实现必须是普适的。针对任何一个 benchmark,我都可以写出比任何框架更快的手动优化,但是那有什么意义呢?在构建一个实际应用的时候,你难道为每一个地方都去做手动优化吗?出于可维护性的考虑,这显然不可能。框架给你的保证是,你在不需要手动优化的情况下,我依然可以给你提供过得去的性能。

2. 对 React 的 Virtual DOM 的误解。

React 从来没有说过 “React 比原生操作 DOM 快”。React 的基本思维模式是每次有变动就整个重新渲染整个应用。如果没有 Virtual DOM,简单来想就是直接重置 innerHTML。很多人都没有意识到,在一个大型列表所有数据都变了的情况下,重置 innerHTML 其实是一个还算合理的操作... 真正的问题是在 “全部重新渲染” 的思维模式下,即使只有一行数据变了,它也需要重置整个 innerHTML,这时候显然就有大量的浪费。

我们可以比较一下 innerHTML vs. Virtual DOM 的重绘性能消耗:

  • innerHTML: render html string O(template size)重新创建所有 DOM 元素 O(DOM size)
  • Virtual DOM: render Virtual DOMdiff O(template size) 必要的 DOM 更新 O(DOM change)

Virtual DOM renderdiff 显然比渲染 html 字符串要慢,但是!它依然是纯 js 层面的计算,比起后面的 DOM 操作来说,依然便宜了太多。可以看到,innerHTML 的总计算量不管是 js 计算还是 DOM 操作都是和整个界面的大小相关,但 Virtual DOM 的计算量里面,只有 js 计算和界面大小相关,DOM 操作是和数据的变动量相关的。前面说了,和 DOM 操作比起来,js 计算是极其便宜的。这才是为什么要有 Virtual DOM:它保证了 ①不管你的数据变化多少,每次重绘的性能都可以接受;②你依然可以用类似 innerHTML 的思路去写你的应用。

3. MVVM vs. Virtual DOM

相比起 React,其他 MVVM 系框架比如 Angular, Knockout 以及 Vue、Avalon 采用的都是数据绑定:通过 Directive/Binding 对象,观察数据变化并保留对实际 DOM 元素的引用,当有数据变化时进行对应的操作。MVVM 的变化检查是数据层面的,而 React 的检查是 DOM 结构层面的。MVVM 的性能也根据变动检测的实现原理有所不同:Angular 的脏检查使得任何变动都有固定的 O(watcher count) 的代价;Knockout/Vue/Avalon 都采用了依赖收集,在 js 和 DOM 层面都是 O(change)

  • 脏检查:scope digest O(watcher count) 必要 DOM 更新 O(DOM change)
  • 依赖收集:重新收集依赖 O(data change)必要 DOM 更新 O(DOM change)

可以看到,Angular 最不效率的地方在于任何小变动都有的和 watcher 数量相关的性能代价。但是!当所有数据都变了的时候,Angular 其实并不吃亏。依赖收集在初始化和数据变化的时候都需要重新收集依赖,这个代价在小量更新的时候几乎可以忽略,但在数据量庞大的时候也会产生一定的消耗。

MVVM 渲染列表的时候,由于每一行都有自己的数据作用域,所以通常都是每一行有一个对应的 ViewModel 实例,或者是一个稍微轻量一些的利用原型继承的 "scope" 对象,但也有一定的代价。所以,MVVM 列表渲染的初始化几乎一定比 React 慢,因为创建 ViewModel / scope 实例比起 Virtual DOM 来说要昂贵很多。这里所有 MVVM 实现的一个共同问题就是在列表渲染的数据源变动时,尤其是当数据是全新的对象时,如何有效地复用已经创建的 ViewModel 实例和 DOM 元素。假如没有任何复用方面的优化,由于数据是 “全新” 的,MVVM 实际上需要销毁之前的所有实例,重新创建所有实例,最后再进行一次渲染!这就是为什么题目里链接的 angular/knockout 实现都相对比较慢。相比之下,React 的变动检查由于是 DOM 结构层面的,即使是全新的数据,只要最后渲染结果没变,那么就不需要做无用功。

Angular 和 Vue 都提供了列表重绘的优化机制,也就是 “提示” 框架如何有效地复用实例和 DOM 元素。比如数据库里的同一个对象,在两次前端 API 调用里面会成为不同的对象,但是它们依然有一样的 uid。这时候你就可以提示 track by uid 来让 Angular 知道,这两个对象其实是同一份数据。那么原来这份数据对应的实例和 DOM 元素都可以复用,只需要更新变动了的部分。或者,你也可以直接 track by $index 来进行 “原地复用”:直接根据在数组里的位置进行复用。在题目给出的例子里,如果 angular 实现加上 track by $index 的话,后续重绘是不会比 React 慢多少的。甚至在 dbmonster 测试中,Angular 和 Vue 用了 track by $index 以后都比 React 快: dbmon (注意 Angular 默认版本无优化,优化过的在下面)

顺道说一句,React 渲染列表的时候也需要提供 key 这个特殊 prop,本质上和 track-by 是一回事。

4. 性能比较也要看场合

在比较性能的时候,要分清楚初始渲染、小量数据更新、大量数据更新这些不同的场合。Virtual DOM、脏检查 MVVM、数据收集 MVVM 在不同场合各有不同的表现和不同的优化需求。Virtual DOM 为了提升小量数据更新时的性能,也需要针对性的优化,比如 shouldComponentUpdate 或是 immutable data。

  • 初始渲染:Virtual DOM > 脏检查 >= 依赖收集
  • 小量数据更新:依赖收集 >> Virtual DOM优化 > 脏检查(无法优化) > Virtual DOM 无优化
  • 大量数据更新:脏检查优化 >= 依赖收集优化 > Virtual DOM(无法/无需优化)>> MVVM 无优化

不要天真地以为 Virtual DOM 就是快,diff 不是免费的,batching 么 MVVM 也能做,而且最终 patch 的时候还不是要用原生 API。在我看来 Virtual DOM 真正的价值从来都不是性能,而是它 ① 为函数式的 UI 编程方式打开了大门;② 可以渲染到 DOM 以外的 backend,比如 ReactNative。

5. 总结

以上这些比较,更多的是对于框架开发研究者提供一些参考。主流的框架合理的优化,足以应对绝大部分应用的性能需求。

,
    推荐阅读
  • 游戏情侣网名(分别是什么名字)

    下面内容希望能帮助到你,我们来一起看看吧!游戏情侣网名花羽霄|风翎絮,寄魚予海|記樹與影,亭书浅墨|黛画生花,雪沁心微凉|暮染绯流觞,西楚何翠鸣|东仙何鹭飞,阙楼月影忆两忘|蒹葭苍苍三更凉,夜白琴鼓奏|花谢灯如昼,听风吹|等君归。北巷长歌悠|南街余音扬,云闲孤飞鹤|意觅知音,曲终何必人散|剧众何必人离。

  • 芬迪家具官方旗舰店(芬迪家具真假争议)

    最近,我们在持续关注一批芬迪家具的真假争议。消费者和经销商福邸国际家居之前达成一致,请品牌方上门检测。现场康经理介绍了LUXURYLIVING和芬迪品牌的关系。不过,汪女士委托的黄律师对康经理的身份产生了质疑。黄律师现场联系奢华集团负责人,一番沟通后,他认为还是难以确认康经理的身份。现场双方关于是否当场上门检测没能达成一致。

  • 怎么正确的看自己的体重(你就知道自己的理想体重了)

    今天,张大夫就以1.7米身高的个体来说明一下如何评价不同个体体重是否达标。现阶段,评价体重是否达标使用最为广泛的指标是BMI指数,BMI指数是指使用体重公斤数除以身高米数平方得出的数字。这个BMI指数可以说是当今国际上使用最多的衡量人体胖瘦程度以及是否健康的一个标准。同样,也可是使用身高体重把BMI指数算出来,自己按照图表对号入座。

  • 希捷铭系列移动硬盘使用方法(用希捷铭系列移动固态)

    为此,我专门入手了希捷的铭系列移动固态硬盘,这次就通过ta在2022年到来之际,给自己创建一份2021年的年度盘点清单吧!颜色选择了清新优雅的蓝色款,除此以外还有商务沉稳的黑色以及高贵轻奢的银色。另外工作需要互传文件、休闲需要视频解闷,由于这款移动固态硬盘都是时刻随身,也能够发挥极大的用处。我是Mac和Windows两用党,都知道Mac要备份文件比较麻烦,起初我还担心希捷铭系列移动固态硬盘无法兼容Mac,但显然有点多余。

  • 上海房价已超一线城市(上海市区房价可能突破三十万每平方米呢)

    实际上上海市区的房价同样受到全世界人们的关注,这里已经是全球数得上的超级大都市了。图片来自网络要知道目前上海市区的房价也已经轻松突破十万每平方米了。甚至个别区能够突破十三四万每平方米,因此我们有理由推测上海房价可以突破二十万,甚至三十万每平方米的大关!

  • 白酒泡肉炒蒜薹怎么做(怎么做出美味的白酒泡肉炒蒜薹)

    白酒泡肉炒蒜薹怎么做工具/原料:五花肉、蒜苔、调料(适量)、食盐(适量)、味精适量、姜(数片)、花椒(6颗)、调和油(适量)、洋葱(适量)、白酒(适量)。洋葱切粒,蒜薹切寸断。热锅冷油,放入花椒粒,洋葱粒爆香。放入干红椒出味,但不要糊。油温上来,放入用酒腌制的肉,翻炒均匀数分钟。五花肉的肉皮变得差不多透明时,有许多油脂也释放出来,此时放入蒜薹。点上适量清开水,放适量盐,味精调味出锅。

  • 炒烩牛肉的做法(炒烩牛肉的做法是什么)

    接下来我们就一起去研究一下吧!炒烩牛肉的做法将所有食材切片,粉条提前泡发备用。锅内倒入食用油烧热,入姜片,洋葱,西红柿,青椒土豆,炒之,可加入适量清水炒出汤汁。再入粉条稍炖片刻。再烩入牛肉,加入生抽,盐,白胡椒炒之。最后,收汁装盘。

  • 手机版wps怎么导入字体(手机wps怎么加入字体)

    手机版wps导入字体的方法是:1、首先打开需要编辑的wps,点击左下角的“工具”图标按钮。

  • 楚乔真实身份暴露(楚乔身上的两个线索让其身世呼之欲出)

    但是楚乔似乎对这些并不是很清楚,应该是失忆了。这个剧情应该是说明,楚乔原来的身份是需要隐藏的,也就是说,楚乔并不是生来就是女奴,而是有另外的不便让人知晓的身份的。从第一集剧情可以看出,楚乔有很高的武功,有养父和兄弟姐妹。除了楚乔后背的彼岸花那印记,还有楚乔手上一直带着的那个镯子,也与楚乔扑朔迷离的身世有关,不少网友猜测,这个手镯后期可能会是身份的一个证明。

  • qq8位号申请工具(手机QQ上线QID身份卡)

    手机QQ上线QID身份卡马上就是QQ会员20周年的日子(2000年12月18日正式推出),为了庆祝20周年最近QQ会员也进行品牌升级,很多地方都有了新的变化1、会员标识QQ会员20周年的主题是“燃鹅”,新版QQ会员、超级会员。