网上都说操作真实 DOM 慢,但霍兰德测试结果分析却比 React 更快,为什么

网上都说操作真实 DOM 慢,但测试结果却比 React 更快,为什么_百度知道网上都说操作真实 DOM 慢,但测试结果却比 React 更快,为什么_百度知道主题信息(必填)
主题描述(最多限制在50个字符)
申请人信息(必填)
申请信息已提交审核,请注意查收邮件,我们会尽快给您反馈。
如有疑问,请联系
傻丫头和高科技产物小心翼翼的初恋
如今的编程是一场程序员和上帝的竞赛,程序员要开发出更大更好、傻瓜都会用到软件。而上帝在努力创造出更大更傻的傻瓜。目前为止,上帝是赢的。个人网站:。个人QQ群:、
个人大数据技术博客:
严格来说,并不是操作DOM对象慢,而是说操作了DOM对象后,会触发一些浏览器行为,比如布局(layout)和绘制(paint),这些个东东导致了“慢”。更多公众号:eaworldEAII(Enterprise Architecture Innovation Institute)企业架构创新研究院,专注于金融、电信、能源、政务等行业领域的企业软件架构优化设计与创新研究以及企业云计算、移动互联、大数据等领域的技术研究。最新文章对这篇文章不满意?您可以继续搜索:百度:搜狗:感谢您阅读为什么使用React作为云平台的前端框架(PPT),本文可能来自网络,如果侵犯了您的相关权益,请联系管理员。QQ:网上都说操作真实dom怎么怎么慢,但是下面这个链接案例中原生的方式却是最快的我在本地也写了个例子循环2000个随机数组,点击按钮重新生成随机数组渲染页面,也是自己用的js 操作dom 比用react 和angular 都要快,这个是怎么回事。测试方式不对,页面元素太少了,还是哪里问题,请帮忙解答下,谢谢。
大家都忽略了一个问题,那就是原作者的 React 写得很烂。我重写了 React 的部分,结果会有趣一些:Benchmark:Source code:正如
所说,题主贴出的 Benchmark,如果第二次 run React ,时间会长到几千 ms ,这肯定不对劲啊。玩玩重写后的版本你就会发现,第一次:第二次:第一次渲染,React 需要建立 Virtual DOM 后再渲染真实 DOM ,当然比 Raw 慢。而之后的每一次渲染,React 都要快过 Raw,这才是 React diff 机制 Awesome 的地方(具体参见
这里面有好几个方面的问题。&br&&br&&b&1. 原生 DOM 操作 vs. 通过框架封装操作。&/b&&br&&br&这是一个性能 vs. 可维护性的取舍。框架的意义在于为你掩盖底层的 DOM 操作,让你用更声明式的方式来描述你的目的,从而让你的代码更容易维护。没有任何框架可以比纯手动的优化 DOM 操作更快,因为框架的 DOM 操作层需要应对任何上层 API 可能产生的操作,它的实现必须是普适的。针对任何一个 benchmark,我都可以写出比任何框架更快的手动优化,但是那有什么意义呢?在构建一个实际应用的时候,你难道为每一个地方都去做手动优化吗?出于可维护性的考虑,这显然不可能。框架给你的保证是,你在不需要手动优化的情况下,我依然可以给你提供过得去的性能。&br&&br&&b&2. 对 React 的 Virtual DOM 的误解。&/b&&br&&br&React 从来没有说过 “React 比原生操作 DOM 快”。React 的基本思维模式是每次有变动就整个重新渲染整个应用。如果没有 Virtual DOM,简单来想就是直接重置 innerHTML。很多人都没有意识到,在一个大型列表所有数据都变了的情况下,重置 innerHTML 其实是一个还算合理的操作... 真正的问题是在 “全部重新渲染” 的思维模式下,即使只有一行数据变了,它也需要重置整个 innerHTML,这时候显然就有大量的浪费。&br&&br&我们可以比较一下 innerHTML vs. Virtual DOM 的重绘性能消耗:&br&&ul&&li&innerHTML:
render html string &b&O(template size)&/b& + 重新创建所有 DOM 元素&b& O(DOM size)&/b&&br&&/li&&li&Virtual DOM: render Virtual DOM + diff &b&O(template size) &/b&+ 必要的 DOM 更新 &b&O(DOM change)&/b&&/li&&/ul&&br&Virtual DOM render + diff 显然比渲染 html 字符串要慢,但是!它依然是纯 js 层面的计算,比起后面的 DOM 操作来说,依然便宜了太多。可以看到,innerHTML 的总计算量不管是 js 计算还是 DOM 操作都是和整个界面的大小相关,但 Virtual DOM 的计算量里面,只有 js 计算和界面大小相关,DOM 操作是和数据的变动量相关的。前面说了,和 DOM 操作比起来,js 计算是极其便宜的。这才是为什么要有 Virtual DOM:它保证了 1)不管你的数据变化多少,每次重绘的性能都可以接受;2) 你依然可以用类似 innerHTML 的思路去写你的应用。&br&&br&&b&3. MVVM vs. Virtual DOM&/b&&br&&br&相比起 React,其他 MVVM 系框架比如 Angular, Knockout 以及 Vue、Avalon 采用的都是数据绑定:通过 Directive/Binding 对象,观察数据变化并保留对实际 DOM 元素的引用,当有数据变化时进行对应的操作。MVVM 的变化检查是数据层面的,而 React 的检查是 DOM 结构层面的。MVVM 的性能也根据变动检测的实现原理有所不同:Angular 的脏检查使得任何变动都有固定的 &b&O(watcher count) &/b&的代价;Knockout/Vue/Avalon 都采用了依赖收集,在 js 和 DOM 层面都是&b& O(change)&/b&:&br&&ul&&li&脏检查:scope digest &b&O(watcher count) &/b&+ 必要 DOM 更新 &b&O(DOM change)&/b&&/li&&li&依赖收集:重新收集依赖 &b&O(data change)&/b& + 必要 DOM 更新 &b&O(DOM change)&/b&&/li&&/ul&可以看到,Angular 最不效率的地方在于任何小变动都有的和 watcher 数量相关的性能代价。但是!当所有数据都变了的时候,Angular 其实并不吃亏。依赖收集在初始化和数据变化的时候都需要重新收集依赖,这个代价在小量更新的时候几乎可以忽略,但在数据量庞大的时候也会产生一定的消耗。&br&&br&MVVM 渲染列表的时候,由于每一行都有自己的数据作用域,所以通常都是每一行有一个对应的 ViewModel 实例,或者是一个稍微轻量一些的利用原型继承的 &scope& 对象,但也有一定的代价。所以,MVVM 列表渲染的初始化几乎一定比 React 慢,因为创建 ViewModel / scope 实例比起 Virtual DOM 来说要昂贵很多。这里所有 MVVM 实现的一个共同问题就是在列表渲染的数据源变动时,尤其是当数据是全新的对象时,如何有效地复用已经创建的 ViewModel 实例和 DOM 元素。假如没有任何复用方面的优化,由于数据是 “全新” 的,MVVM 实际上需要销毁之前的所有实例,重新创建所有实例,最后再进行一次渲染!这就是为什么题目里链接的 angular/knockout 实现都相对比较慢。相比之下,React 的变动检查由于是 DOM 结构层面的,即使是全新的数据,只要最后渲染结果没变,那么就不需要做无用功。&br&&br&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 快: &a href=&///?target=http%3A//vuejs.github.io/js-repaint-perfs/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&dbmon&i class=&icon-external&&&/i&&/a& (注意 Angular 默认版本无优化,优化过的在下面)&br&&br&顺道说一句,React 渲染列表的时候也需要提供 key 这个特殊 prop,本质上和 track-by 是一回事。&br&&br&&b&4. 性能比较也要看场合&/b&&br&&br&在比较性能的时候,要分清楚初始渲染、小量数据更新、大量数据更新这些不同的场合。Virtual DOM、脏检查 MVVM、数据收集 MVVM 在不同场合各有不同的表现和不同的优化需求。Virtual DOM 为了提升小量数据更新时的性能,也需要针对性的优化,比如 shouldComponentUpdate 或是 immutable data。&br&&br&&ul&&li&初始渲染:Virtual DOM & 脏检查 &= 依赖收集&/li&&li&小量数据更新:依赖收集 && Virtual DOM + 优化 & 脏检查(无法优化) & Virtual DOM 无优化&/li&&li&大量数据更新:脏检查 + 优化 &= 依赖收集 + 优化 & Virtual DOM(无法/无需优化)&& MVVM 无优化&/li&&/ul&不要天真地以为 Virtual DOM 就是快,diff 不是免费的,batching 么 MVVM 也能做,而且最终 patch 的时候还不是要用原生 API。在我看来 Virtual DOM 真正的价值从来都不是性能,而是它 1) 为函数式的 UI 编程方式打开了大门;2) 可以渲染到 DOM 以外的 backend,比如 ReactNative。&br&&br&&b&5. 总结&/b&&br&&br&以上这些比较,更多的是对于框架开发研究者提供一些参考。主流的框架 + 合理的优化,足以应对绝大部分应用的性能需求。如果是对性能有极致需求的特殊情况,其实应该牺牲一些可维护性采取手动优化:比如 Atom 编辑器在文件渲染的实现上放弃了 React 而采用了自己实现的 tile-based rendering;又比如在移动端需要 DOM-pooling 的虚拟滚动,不需要考虑顺序变化,可以绕过框架的内置实现自己搞一个。
这里面有好几个方面的问题。 1. 原生 DOM 操作 vs. 通过框架封装操作。 这是一个性能 vs. 可维护性的取舍。框架的意义在于为你掩盖底层的 DOM 操作,让你用更声明式的方式来描述你的目的,从而让你的代码更容易维护。没有任何框架可以比纯手动的优化 DOM 操…
对于使用原生DOM接口操作大片DOM而言:&br&&br&&ol&&li&如果对DOM创建过程稍作优化,首次创建必定比所有框架或者库都快。&br&&/li&&li&如果对DOM变更过程做相对复杂的优化,它会比大多数框架或者库都快。&br&&/li&&li&如果想要DOM的变更过程更快,需要作更加复杂的优化。&br&&/li&&/ol&&br&很多时候大家讨论某些东西的快慢,是基于完全不优化的方式的,这时候得出一个原生操作更慢的结论也不奇怪。实际上,对于每个框架或者库,对于其中的不同DOM操作类型,基本都存在针对性的优化方式,可以大幅提升性能。
对于使用原生DOM接口操作大片DOM而言: 如果对DOM创建过程稍作优化,首次创建必定比所有框架或者库都快。 如果对DOM变更过程做相对复杂的优化,它会比大多数框架或者库都快。 如果想要DOM的变更过程更快,需要作更加复杂的优化。 很多时候大家讨论某些东西…
已有帐号?
无法登录?
社交帐号登录
Web and beyond

我要回帖

更多关于 如何正确的使用慢玩 的文章

 

随机推荐