怎么更好的理解react虚拟domM

网上都说操作真实dom怎么怎么慢,但是下面这个链接案例中原生的方式却是最快的我在本地也写了个例子循环2000个随机数组,点击按钮重新生成随机数组渲染页面,也是自己用的js 操作dom 比用react 和angular 都要快,这个是怎么回事。测试方式不对,页面元素太少了,还是哪里问题,请帮忙解答下,谢谢。
这里面有好几个方面的问题。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 DOM + diff O(template size) + 必要的 DOM 更新 O(DOM change)Virtual DOM render + diff 显然比渲染 html 字符串要慢,但是!它依然是纯 js 层面的计算,比起后面的 DOM 操作来说,依然便宜了太多。可以看到,innerHTML 的总计算量不管是 js 计算还是 DOM 操作都是和整个界面的大小相关,但 Virtual DOM 的计算量里面,只有 js 计算和界面大小相关,DOM 操作是和数据的变动量相关的。前面说了,和 DOM 操作比起来,js 计算是极其便宜的。这才是为什么要有 Virtual DOM:它保证了 1)不管你的数据变化多少,每次重绘的性能都可以接受;2) 你依然可以用类似 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 快:
(注意 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 真正的价值从来都不是性能,而是它 1) 为函数式的 UI 编程方式打开了大门;2) 可以渲染到 DOM 以外的 backend,比如 ReactNative。5. 总结以上这些比较,更多的是对于框架开发研究者提供一些参考。主流的框架 + 合理的优化,足以应对绝大部分应用的性能需求。如果是对性能有极致需求的特殊情况,其实应该牺牲一些可维护性采取手动优化:比如 Atom 编辑器在文件渲染的实现上放弃了 React 而采用了自己实现的 tile-based rendering;又比如在移动端需要 DOM-pooling 的虚拟滚动,不需要考虑顺序变化,可以绕过框架的内置实现自己搞一个。
对于使用原生DOM接口操作大片DOM而言:如果对DOM创建过程稍作优化,首次创建必定比所有框架或者库都快。如果对DOM变更过程做相对复杂的优化,它会比大多数框架或者库都快。如果想要DOM的变更过程更快,需要作更加复杂的优化。很多时候大家讨论某些东西的快慢,是基于完全不优化的方式的,这时候得出一个原生操作更慢的结论也不奇怪。实际上,对于每个框架或者库,对于其中的不同DOM操作类型,基本都存在针对性的优化方式,可以大幅提升性能。
Google一名员工的测试结果 。测试中显示了使用直接操作 DOM (Vanilla 方式)的方式要比React快三倍。测试用例是一个 Flickr 照片流的应用。操作 DOM 的地方就是用户每点击一次 "Add Images" 按钮,就添加 100 张图片(大约500个 DOM Elements)。其实这个例子仅仅说明了,在插入“只读”的 DOM Elements 的场景下,Vanilla 方式要比 React 快。这个例子得到这样的结果是正常的。这些插入的 DOM Element 是只读的,那么任何框架都只可能是比 Vanilla 方式慢,毕竟要添加抽象。React 的性能优势在 Diff,而这个场景根本没 Diff 啥事。React 帮助在复杂的界面环境下,如何尽量降低 DOM Reflow 的成本。稍微复杂一点的 WebApp ,对 DOM 的操作是非常综合的,CRUD都有。而一旦出现了频繁变化,DOM Reflow 的开销就变得非常大。React 的 Diff 就是解决这个最痛的问题的。更何况当 WebApp 复杂到一定程度之后,不依赖 Angular、Ember 或者 React 这样的框架,你的代码就会完全失控,更何谈性能调优。原作者也提到了 React 在工效方面(ergonomics)的优秀性。另外,大家用 React 的时候如果发现性能问题,先注意是不是用了 minified 的版本。文章的作者一开始也没注意这一点。生产版的 React 比 Debug 版的要快不少。
各按两次或以上,比较最后一次的时间。详细原理可以在知乎里查 "虚拟DOM":
。大致原理是,第一次渲染,大家都是往空的div里插入新的元素,react还多了个创建虚拟DOM的过程,自然较慢。但第二次往后,raw的一般思路是删了原来的元素重新创建元素插入。而react是在虚拟DOM上做比较,对实际的DOM只修改有变动的部分。就这个例子来说,修改原有元素的文本就行了,不需要走 "删除-创建-插入" 的步骤。当然,浏览器渲染最终还是靠DOM,你有针对性的去优化操作DOM的逻辑(比如说在这个例子里你也在第二次渲染时只修改文本而非删除后再插入),最终肯定能比react快,只不过代码写起来很费时且很难看而已。
个人觉得这种快应该这样理解:在传统的jquery开发中,大家都很随意,大多数程序员都不会全面考虑dom操作慢的问题的,由于种种原因,写出各种混乱的直接操作dom的代码,这肯定会造成最终产生的应用变得比较慢。而react对dom操作做了一层优化,逼迫开发者按照他的方式去做界面操作,以便react做集中的优化处理,这样做出来的应用,很可能就比较快。所以总结起来就是说,用react写出来的应用更容易变得比较快。
鉴于有人表示没有看懂。 下面是结论:题主测试结果反常是因为测试用例构造有问题。React.js 相对于直接操作原生DOM有很大的性能优势, 背后的技术支撑是基于virtual DOM的batching 和diff.React.js 的使用的virtual DOM 在Javascript Engine中也有执行效率的优势。 如果想知道解释,请继续阅读。。-----------------------------------------看了好几个答案感觉都没有答到点子上面。如果一个框架发明出来就是为了提高性能,那就一定要在性能上面有所体现。编程模型类型框架实在是太多太多,React.js仅仅因为这个不可能会那么受好评。 React.js仅仅是做MVC中的View,也就是渲染层,任务其实非常单一的,也没有那么多哲学方面的东西需要承载。 1.题主测试结果反常是因为测试用例构造有问题。我们来看看题主的测试用例(由于题主问的react.js 和原生,所以其他的我都去掉了).以下所有的代码都在:原生 (只保留了关键代码,其他都去掉了,这样看得更清楚一点)这里看出问题没?
这里看出问题没?
整个测试用例的模式是:
构造一个 String, 包含一个1000个 Tag。把这1000个 Tag 一次性添加到 DOM 树中。其实,题主的测试用例只做了一次 DOM 操作。。而且主要问题是,如果你真的做一个WebAPP,
然后直接操作DOM更新,更新的模式完全不是这样子的。在现实中,更新模式更像这个样子滴:同样是 1000 元素需要更新, 你的界面上面分成了20个逻辑区域(或者层,或者 view, 或者whatever 框架取的名字),
每个区域 50 个元素。在界面需要更新的时候,每个逻辑区域分别操作 DOM Tree 更新。
那么代码看起来更像是这样子的:然后我们再来看看结果天了撸, 发生了什么, 原生的怎么慢这么多。(React.js 并不需要修改,无论如何每个区域都是把新的操作作用在Virtual DOM上面,然后每帧只会调用一次Render)。2. React.js 相对于直接操作原生DOM有很大的性能优势, 背后的技术支撑是基于virtual DOM的batching 和diff。原生DOM 操作慢吗?做为一个浏览器内核开发人员, 我可以负责任的告诉你,慢。
你觉得只是改变一个字符串吗?我们来看看你在插入一个DOM元素的时候,发生了什么.我们来看看你在插入一个DOM元素的时候,发生了什么.实际上,浏览器在收到更新的DOM Tree需要立即调用HTML Parser对传入的字符串进行解析,这个,呃,耗的时间可不是字符串替换可以比的哦 .(其实你们已经处于一个好时代了,换做几年前,浏览器还可能会花几秒到几分钟给你Reflow一下)这个例子还算简单的了,如果你插入的标签里面包括了脚本,浏览器可能还需要即时编译的你脚本(JIT).
这些时间都算在你的DOM操作中的哦。我们再来看看统计。131 ms 都花在了Loading 里面(ParseHTML)。另外注意一些细节,Profiler 报告整个函数使用了418ms, 因为有些时间在JS里面是统计不到的,比如Rendering的时间, 所以, 多用Profiler.我们再来看一个图, 这个原测试用例的Profiling, 1000 Tag 一次插入呃,如果你还没有看出端倪的话,我提示一下: 这里的解析时间(Loading)降到了13 ms.同样的数据(1000 元素),分20次解析, 每次解析50个,耗时是 一次性解析的 10 倍左右。。也就是说,有9倍开销,都花在了DOM函数,以及背后的依赖的函数本身的开销上了。 DOM 操作本身可能不耗时,但是建立上下文,层层传递的检查的开销就不容小视了。
这个官方称为”API Overhead”.
改变DOM 结构的调用都有极其高的API Overhead.而对于Overhead高的API,标准解决办法就是两个:Batching 和 Diff.Diff 大家都比较了解, Batching是个啥? 想象在一个小山村里面,只有一条泥泞的公路通向市区,公交车班次少,每次要开半个小时,如何保证所有乘客最快到达目的地?
搜集尽量多的乘客,然后一次性的把它们运往市区, 这个就是Batching.
如果你搜下React.js 的文档里面。这里有专门提到:
“ You may be thinking that it's expensive to change data if there are a large number of nodes under an owner. The good news is that JavaScript is fast and `render()` methods tend to be quite simple, so in most applications this is extremely fast. Additionally, the bottleneck is almost always the DOM mutation and not JS execution. React will optimize this for you using batching and change detection.“
这个才是React.js 引入Virtual DOM 的精髓之一, 把所有的DOM操作搜集起来,一次性提交给真实的DOM. Batching 或者 Diff, 说到底,都是为了尽量减少对慢速DOM的调用。类似技术在游戏引擎里面(对 OPENGL 的Batch), 网络传输方面( 报文的Batch), 文件系统读写上都大量有使用。3. React.js 的使用的virtual DOM在Javascript Engine中也有执行效率的优势Virtual DOM 和 DOM 在JS中的执行效率比较。-------------------------------------------前方高能预警, 一般前端开发不需要了解那么多,不过如果你如果都看懂了,来欧朋浏览器面试吧 :) 抛开浏览器内核开销不算, 从Javascript 执行效率来讲,Virtual DOM 和DOM之间到底有多大差别呢? 这个其实可以回答Virtual DOM 到底有多快这个问题上面。 了解这个问题,需要了解浏览器内核,DOM以及网页文档到底都是什么关系。很吃惊吧。
其实DOM 完全不属于Javascript (也不在Javascript 引擎中存在).
Javascript 其实是一个非常独立的引擎,DOM其实是浏览器引出的一组让Javascript操作HTML文档的API而已。
如果你了解Java的话,这个相当于JNI.
那么问题就来了,
DOM的操作对于Javascript实际上是外部函数调用。 每次Javascript 调用DOM时候,都需要保存当前的上下文,然后调用DOM, 然后再恢复上下文。 这个在没有即时编译(JIT)的时代可能还好点。 自从加入即时编译(JIT),
这种上下文开销简直就是。。惨不忍睹。
我们来顺便写一段Javascript.然后在v8里面跑一跑(直接使用v8 sample中的shell ).
由于v8 单独的Shell中不存在DOM, 我们用print代替, print 是外部函数, 调用它和调用DOM是一回事。调用的堆栈看起来是这样的。这里可以看到V8是如何执行JIT代码,然后JIT代码调用到Print的过程
(JIT 代码就是没有符号的那一堆,Frame #1 - #5.)我们来看看v8 JIT 生成的代码.看到这里还算合理, 一个call调走,不过我们来看看 CallApiAccessorStub是个什么鬼:60+ 条额外指令用于保存上下文和堆栈检查。。我靠,我就调个函数,你至于吗..当然,现代的JIT技术已经进步很多了,换到几年前,这个函数直接就不JIT了 (不编译了, 在V8中即不优化,你懂的,慢10到100倍).而Virtual DOM的执行完全都在Javascript 引擎中,完全不会有这个开销。什么,你说我第一个测试结果里面两边的速度就差一半嘛(117 ms vs 235 ms),react.js还只是做了一次DOM操作,原生的可是做了50次哦, 你说的virtual DOM框架完全不会有开销是几个意思?我们来稍微改改测试代码。给你们每个条目加个标示符,这样每次更新的DOM都不一样,我看React.js你怎么做Diff, 哇哈哈哈哈哈.给你们每个条目加个标示符,这样每次更新的DOM都不一样,我看React.js你怎么做Diff, 哇哈哈哈哈哈.然后你可以多点几次React的测试按钮,一般来说来,第二次以后, 你就可以看到性能稳定在这个数字。
这个是个什么情况? 这个可不是React.js Diff的功劳哦?因为我们每次的更新都是完全不同的,它木有办法占便宜做Diff哦。。
这个其实是Javascript 引擎的工作特性引起。Javascript 引擎目前用的都是即时编译(JIT). 所以
第一次点击运行的时候所耗的时间 = 框架被编译的时间(JIT) +
执行时间之后执行的时间 = 执行时间。所以, 53 ms那个才是Virtual DOM 的真实执行性能哦, 是不是觉得好快呀。当然, v8的JIT方法还要特殊一些, 他是两次编译的, 第一次粗编译,第二次会把执行很多的函数进行精细编译. 所以第三次以后才是最快的时间。两次编译虽然很有趣也很有用,鉴于这个帖子实在是太长了,这里就不讲了。 有兴趣看这个:原测试用例在测react第二次运行的时候会很慢(大概4s左右),
原因是这个:onClick: this.select.bind(null, this.props.data[i])bind 会每次创建一个新的函数对象,于是原测试里面每次点击会创建1000个新的函数对象。恭喜原作者,JS的内存真是不要钱。。我的测试用例里面暂时去掉了,彻底修复可以不用bind, 指向一个函数即可,然后用其他方法为每个列表项保存状态。-------------------------------------------------------------------------------------------------------------回答
@你用的技巧称为是 DocumentFragment,
参见这个改善性能技巧早期流行其实主要是防止浏览器在JS修改DOM的时候立即Reflow。(防止你在修改了DOM以后立即取元素大小一类的)。这个技巧在现代浏览器里面基本没有作用,因为,基本上Reflow和Layout都是能延迟就延迟。不相信的话你这样写var tplDom = document.createElement('div');
container.appendChild(tplDom);
tplDom.innerHTML =
html = '';
tplDom先加入global DOM然后在修改,这个算是刷global DOM了吧?在chromium里面没有任何区别的。我更改以后的测试用例里面就是这样写的:)所以,这个和刷不刷global DOM没有任何关系的。你看到的性能提升,其实是避免了container.innerHTML +=中+=, 因为+= 是其实是一个替代操作,而不是增量操作。另外, 你测出来的只是插入新元素时间而代码里面还需要删掉之前的节点的代码.因为对于react.js第一次运行时间 = JIT时间+插入时间多次以后 = 更新节点时间。 (v8优化器原因)而更新节点 = 删除节点+插入新的节点 (你也可以用replaceChild, 性能没有能测出来差异).react.js由于第一次运行带着JIT,所以没有办法剥离出来纯插入时间。于是加入删除之前节点的代码,然后多次运行测试更新节点的时间才是有比较性的。修改后的测试用例在你可以试试,这个是我这里测出来的结果。很接近了是不是?不可否认这是一个非常好的优化,是不是觉得React已经没有什么优势?少年,你太天真了,浏览器这个世界很险恶的,我刚才说Layout和Reflow被怎么了来着? 被延迟了。。我们来看看profiler的输出。React 的性能统计Raw的性能统计Raw的性能统计事实上React的耗用的时间的是80m, 而优化后的Raw也有144 ms,
接近一半的时间。为蜀莫呢?有个31ms 和95ms的rendering差别,而在这个例子里面, rendering = Recalculate Style 和Layout(参见上面的堆栈,或者你自己也可以试试)。而这个差异,在JS里面是测不到了,因为, 呃,他们被延迟了。。原因也很简单,React 修改的粒度更小。virtual DOM每次用Batch + diff来修改DOM的时候, 假如你有个&span class=''123"& abc&/span&如果只是内容变了,那spanNode.textContent会被换掉, style啥的不会动。 而在原生例子里面,整个spanNode被换掉。浏览器: 你把整个节点都换了,我肯定只能重新计算style和layout了, 怪我咯。从本质上面讲, react.js 和自己写算法直接操作原生的DOM是这样一个关系:修改的内容 -& React.js -& DOM操作修改的内容 -& 你的算法 -&
DOM操作React.js 和你的算法最后都是把特定的意图翻译成一组DOM操作,差别只是谁的翻译更加优化而已而原回答其实想说明的时候,react.js 在使用virtual DOM这套算法以后DOM操作在通常情况下比自己的写是优化非常多的。这个其实是对“使用react.js和(用自己算法)操作DOM哪个快”这个问题的直接回答。 而你当然可以进一步优化算法,在特定的环境下面接近或者超过React, 不过,这个在实际开发中并没有适普性。这个其实和问编译器和手动汇编哪个快是一模一样算法 -& 原代码 -&编译器-&汇编算法 -&手动翻译-&汇编而在目前CPU的复杂程度下,手动翻译反而大部分时间比不上编译器, 复杂度越高,需要考虑的变量越多,越容易用算法来实现而人脑总是爱忘东西的。不可否认是原测试用例里面的不管是测raw还是测react的的算法都写得很有问题。所以对原回答中只是尽量不做大的修改来说明问题而已。最后还要感谢你的提问,否则没法讲得这个深度,其实在写virtual DOM JIT那一段的时候我就很犹豫是不是讲得有点过了。-----------------------------------------------------------------------------------------------------------回答
呃。。你说的这句话是吧 - “发明出来就是为了提高性能” 以及 “没有那么多哲学方面的东西需要承载”。既然我们讨论的是“发明出来”, 我们就来看看原团队的意思咯, 戳这里, 这个原团队的blog post:-- 摘要如下:Why did we build React?There are a lot of JavaScript MVC frameworks out there. Why did we build React and why would you want to use it?React isn't an MVC framework.....React doesn't use templates....Reactive updates are dead simpleReact really shines when your data changes over time.....Because this re-render is so fast (around 1ms for TodoMVC), the developer doesn't need to explicitly specify data bindings. We've found this approach makes it easier to build apps....这个才是全文重点, 请再次默念下“really shines”这篇Post翻译成大白话就是:哥做了一个框架, 有这个功能,还有这个功能,但是最牛逼的功能就是:你的数据变的时候渲染的特别快哦, 快得你们爱怎么搞怎么搞。真的不是性能嘛?...PS: 虽然我觉得你说得很有道理,他们都是react.js的好处啦,不过就从"why"来说但是“通过引入函数式思维来加强对状态的管理”, 貌似木有在“why”里面提到?第三方那个我木有找到引用。而“Virtual DOM 可以渲染到非 DOM 的后端从而催生 ReactNative”, 是在:“Because React has its own lightweight representation of the document, we can do some pretty cool things with it:”
听起来貌似是:
“React really shines when your data changes over time.
In a traditional JavaScript application, you need to look at what data changed and imperatively make changes to the DOM to keep it up-to-date. Even AngularJS, which provides a declarative interface via directives and data binding .
React takes a different approach.”的副产品哦(by-product).
举个例子,实际的。富文本编辑器中的粘贴功能,取到字符串的html字符。ctrl v的时候你需要分析这一段html字符串中的节点信息,比如是否格式化,是否重置style样式,然后再创建节点插入页面。完成复制。这一过程中无疑使用dom api完成分析比较快捷。正则错误率高还复杂。测试无论chrome还是ie 原生api的方法都要比虚拟dom慢。比如getTagname getStyle 都是非常消耗性能的 比如获取前后节点信息 父子节点信息。这时虚拟dom也就是假的parent child next prev getTags 等方法速度可是原生的很多倍。。尤其复杂关系结构。我只说这一个例子。。手机打的 别见怪。。。方法写的不全。ps 没用react 但是用过虚拟dom优化
大家都忽略了一个问题,那就是原作者的 React 写得很烂。我重写了 React 的部分,结果会有趣一些:Benchmark:Source code:正如
所说,题主贴出的 Benchmark,如果第二次 run React ,时间会长到几千 ms ,这肯定不对劲啊。玩玩重写后的版本你就会发现,第一次:第二次:第一次渲染,React 需要建立 Virtual DOM 后再渲染真实 DOM ,当然比 Raw 慢。而之后的每一次渲染,React 都要快过 Raw,这才是 React diff 机制 Awesome 的地方(具体参见
一般随机数据的情况下,近似可以认为DOM变更在50%左右,倘若基数又大,那么直接innerHTML进行一次性重绘的时间记作t1,vd比对的时间记作t2,vd更新真实DOM的时间记作t3。显然2者对比是t1和t2+t3的对比,在这种情况下由于t2的时间消耗导致t1反过来可能比t2+t3的时间要少。这个问题和测试凑巧前天和同事也讨论对比过。显然2者对比是t1和t2+t3的对比,在这种情况下由于t2的时间消耗导致t1反过来可能比t2+t3的时间要少。因为t3=t1/2,而t2可能会&t3。50%的变更率实际上是一个非常大的变更,在现实环境中非常难以见到,所以还没引起足够的重视和优化。当更多问题暴露出来的时候,需求就会有了,那么此时应该增加一种设计接口:即在知道明显某个区域是大变化,应该省略diff直接进行重绘的时候,提供兼容易用的API显示声明这里别再diff,直接toString()渲染即可。另外react的vd对于text节点类型的span封装也造成了一些性能浪费,即便不考虑DOM侵入和语义、css干扰。innerHTML: react: migi:
直接操作DOM当然是最快的,但是如果你亲自来写这种底层代码的话,实际做业务需求的时候会死的…………这就好像说直接用汇编写的程序必然快于所有其他语言,但几乎不存在任何人直接用汇编写商务程序一样至于React.js和Angular之流的区别,主要就是看你更喜欢用模块化的方式还是喜欢用MVVM表达自己了。当然两边都在进化。
已有帐号?
社交帐号登录
无法登录?
社交帐号登录

我要回帖

更多关于 jquery 虚拟dom 的文章

 

随机推荐