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

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

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

出于可维护性的考虑,这显然不可能。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. 总结

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

,
    推荐阅读
  • 7月24日白云区太和镇九价HPV疫苗预约包三针吗

    预约时间:2022年7月24日15:00预约流程:1、下载“医鹿”App。选择接种日期和时间,填写接种人信息,系统会在线核实是否符合疫苗接种条件,是否本人实名账户,只有符合条件的用户才可进行预约。),两个接种点的预约号不互通,请根据自己需求预约合适的接种点,跨点不予接种。

  • 习惯了当观众就成为不了主角(大幕开启告诉观众)

    1949年5月27日,是中国现代史上一个值得铭记的日子。震惊海内外的上海战役在这一天结束,中国第一大城市上海宣告解放,回到了人民的怀抱。72年后的2021年5月27日,也是值得纪念的。《大幕开启》成功地回答了这个问题。战上海,不是要打烂上海,而是为了保护这座城市。舞台上演员的精彩表演,让观众拍手称快。新生的上海,电灯是亮的,自来水未停,电话畅通,工厂学校保护完好,人民解放军创造了战争史上的奇迹。

  • 手机拍摄视频的技巧(手机拍视频的基本步骤)

    晚上的灯光就算再亮,拍出来的颜色和效果也会有偏差的。想要取消锁定曝光,轻敲两下屏幕即可。②添加所有转场:一键添加所有转场,让视频衔接更自然。⑦片头片尾制作:这部分可有可无,看个人。⑧加音效/贴纸:根据视频效果适当添加。⑨检查调整,确认导出。

  • 卷腹能瘦肚子两侧的肉吗(腰腹两侧赘肉多)

    方法1、控制卡路里摄入,给身体创造热量缺口减肥不止要从运动入手,还需要从饮食入手。想要避免腰腹赘肉的堆积,我们一定要控制卡路里摄入,学会用低热量食物代替高热量食物,才能有效控制卡路里摄入,给身体创造热量缺口,促进身体调动更多脂肪分解,才能让你慢慢瘦下来。我们要学会多喝水,定时起来活动,促进血液循环,养成规律三餐的习惯,做到早睡不熬夜,可以抵抗衰老速度,保持旺盛的体能状态,抑制脂肪堆积。

  • 紫甘蓝不能与什么食物同食(哪些食物不能和紫甘蓝一起吃)

    下面更多详细答案一起来看看吧!紫甘蓝不能与什么食物同食苹果紫甘蓝不能和苹果一起吃,这样会大大的影响身体对维生素的吸收。虾据研究表明紫甘蓝不适合和虾一起吃,因为紫甘蓝中含有比较丰富的维生素C,如果和虾一起吃可能会导致中毒。黄瓜黄瓜中含有分解酶物质,紫甘蓝中的维生素C含量比较丰富,二者结合黄瓜能分解掉紫甘蓝的维生素C,导致身体吸收维生素C的含量降低,因此也会让两种食材的营养价值降低。

  • 端午节宜什么忌什么(五月初五端午节)

    挂艾草不仅能防止蚊虫入室,还寓意“招百福”,保佑一家人身体健康。以死明志,其决绝的行为,为国、为民,感天动地。因为雨后的潮湿闷热不仅容易让麦粒在麦秆上面发芽生长,还会让收割完的小麦无法进行正常的晾晒,从而导致发霉、造成严重的经济损失。对于喜欢在河里游泳、河边玩水的大人孩子来说,水位上涨容易导致溺水的悲剧发生,尤其是在端午节假期期间,更是多发。因此,在端午节,不宜去河中游泳、洗澡。

  • 教诲的诲怎么组词(汉字诲怎么组词)

    下面内容希望能帮助到你,我们来一起看看吧!教诲的诲怎么组词诲人不倦[huìrénbùjuàn]教导人特别耐心,从不厌倦。训诲[xùnhuì]教导。慢藏诲盗[màncánghuìdào]慢:懈怠,怠慢。收藏财物不谨慎,等于告诉盗贼,可以来偷东西。指因保管疏忽而招致盗窃。孜孜教诲[zīzījiàohuì]恳切、耐心地启发开导。诲淫[huìyín]引诱别人产生淫欲。诜诲[shēnhuì]不妒忌则子孙兴旺的教诲。诲迪[huìdí]教诲开导。

  • 手指甲有小坑是缺什么 手指甲有个坑是怎么回事缺什么

    可能是缺蛋白质手指甲的成分主要由蛋白质组成,当人体缺乏蛋白质时,就会影响到指甲的发育,导致指甲出现坑坑洞洞的怪相。可能是缺钙指甲除了由蛋白质组成外,还含有钙,钙质不仅是保证指甲的韧性的必要元素,还是保持指甲光泽、平坦必不可少的养分,若患者自身缺钙,那么也会对指甲造成影响,出现指甲有小坑小洞的症状。

  • 实体书店还有人买书吗(图书市场逐渐回暖)

    日前,开卷公布了《2020前三季度图书零售市场报告》,数据显示图书市场逐渐回暖,实体店渠道降幅收窄。据钟书阁书店相关负责人介绍,以钟书阁北京融科店为例,目前客流量平时800人左右,周末2000人左右,已恢复到本次疫情前的80%,“北京的读者‘报复性逛书店’非常明显。”据介绍,以建投书局北京国贸店而言,就近一两个月的数据来看,平均每日客流量较二季度增长超过40%,销售额也接近去年同期水平。

  • 冬天里的蚊子去哪了(你知道冬天蚊子去哪了吗)

    你知道冬天蚊子去哪了吗小时候就有想过,冬天的时候,基本上看不到蚊子的踪迹,但天气一转暖,它们就会卷土重来那么冬天蚊子到底去哪了呢?原来啊,它们通常在衣柜后,墙缝、管道等缝隙处过冬那你知道为什么秋天的蚊子最厉害吗?因为他们也。