内容简介:我们总是或多或少的听说过直接操作DOM是低效和缓慢的。然而,我们几乎没有可用的数据来支持这个观点。关于React虚拟DOM的令人愉悦的地方在于web开发过程中,它采用了更加高效的方式来更新view层。我们把使用React的其他好处姑且放到一边,例如单项绑定和组件化。本节我讲详细的讨论一下虚拟DOM,随后公正的抉择为什么使用React而不是其他UI库(或者任何UI库都不使用)。在反应式的系统中两个最重要的idea应该是事件驱动和对数据变化的响应。
我们总是或多或少的听说过直接操作DOM是低效和缓慢的。然而,我们几乎没有可用的数据来支持这个观点。关于React虚拟DOM的令人愉悦的地方在于web开发过程中,它采用了更加高效的方式来更新view层。
我们把使用React的其他好处姑且放到一边,例如单项绑定和组件化。本节我讲详细的讨论一下虚拟DOM,随后公正的抉择为什么使用React而不是其他UI库(或者任何UI库都不使用)。
为什么需要UI库
在反应式的系统中两个最重要的idea应该是事件驱动和对数据变化的响应。
DOM用户接口组件有内部状态,当无论何时有情况发生变化的时候,更新浏览器并不是像简单的重新生成DOM那么简单。举个例子,如果Gmail曾经这么做的话,因为浏览器窗口为了显示新的信息,需要不断的刷新整个页面,如果你正在写邮件的话,所有的都会被清除,你一定会经常恼怒不已。
DOM的这种状态方式决定了为什么我们需要一个用户界面库,因为这些库提供了一些解决方案,例如键/值 观察(在Ember库中使用了此方法),或者脏值检测(Angular使用了此方法)。UI库可以观察数据模型的改变,然后在改变发生的时候只改变对应的部分DOM,或者观察DOM改变,然后更新数据模型。
这种观察和更新的模式叫做双向绑定,这种方式常常让与用户界面的工作更加复杂和让人困惑。
React的不同之处
React的虚拟DOM与其他库的不同之处在于从 程序员 的角度看,这种模式更加的简单。你只需要写纯javascript,然后更新React组件,React将为你更新DOM。数据绑定并没有和应用程序搅和在一起。
React使用单向数据绑定使得事情变得更加简单,每一次在ReactUI的input域中输入内容,React并不直接改变状态。相反,React更新数据模型,随后引起UI更新,你输入的文字将在域中出现。
DOM真的慢吗?
关于虚拟DOM的很多演讲和文章都指出,尽管现在jiavascript的引擎已经很快了,但是读取和写入浏览器的DOM还是很慢,
这不是特别的准确。DOM是很快的。增加和去除DOM节点就是设置一些javascript对象的属性,这才是简单的操作,这并不是需要做很多的工作。
真正慢的地方自在于,每次DOM改变的时候,都需要在浏览器中进行渲染。每一次DOM改变的时候,浏览器都需要重新计算CSS,进行布局处理,然后重新渲染页面。这都需要时间。
浏览器的开发者持续不断的工作来缩短渲染页面的时间。最关键的需要完成的事情是最小化DOM改变,然后批处理DOM变化,在必要的时候才重新渲染页面。(目前原生浏览器还是无法做到)
这种批处理DOM改变的策略,把我们提升到了一个更加抽象的层次,这也是React虚拟DOM背后的idea。
虚拟DOM是怎么工作的?
与真实DOM相似,虚拟DOM也是节点树,以对象的形式列出内容,属性。React的render方法从React组建中创建节点树,因为动作改变等引起数据模型变化的时候,React更新节点树。
每次React app内部的数据改变,用户界面的虚拟DOM都会构建。
这里就是最有趣的地方,在React中更新浏览器DOM需要三步: 1. 每次数据模型变化的时候,虚拟DOM节点树都会重新构建。 2. React依赖某个算法(称之为diff算法)来与上一个虚拟DOM节点数进行比较,只有在不同的情况下才重新进行计算。 3.所有的变化要经过批处理,完成之后,真实DOM才进行更新。
虚拟DOM慢吗?
有人认为只要有一点改变就重新构造整个虚拟DOM节点树有点浪费,但是他没有提及一个事实,React在内存中存储有两个虚拟DOM树。
但是,真实情况是渲染虚拟DOM总是比直接渲染浏览器DOM快。这种论断与你使用的浏览器也没多大的关系。
我们看一些数据
我不会做一些基准测试,因为已经有很多开发者创建了很多测试来搞清楚React虚拟DOM方法是否比原生的DOM渲染更加快速。但是频繁的结论显示似乎不是这样,但是因为很多测试都是不实际的,所以这些测试结果也无关紧要。
简单来说,虚拟DOM就是把所有浏览器为了最小化DOM操作,这些对于开发者来说透明的操作进行了抽象。这层额外的抽象的缺点就是增加了CPU的开销。
这里有一个"hello,world"的例子,使用了原生的DOM操作:
随后我们在React中做相同的事情。在这里请注意我们需要包含React,React DOM 和babel,其中babel负责把在render方法中的类XML的代码进行转换成原生的javascript。
结果显示,本地方法更加的快速。这并不是开玩笑,让我们看一下证据。
这里是加载和渲染真实DOM的性能分析图。(来源于Chrome)
这里是在同样的浏览器中加载和展示React的"hello,world"应用时间线。
请注意本质上来说,事情是相同的。React比直接操作DOM慢,而且慢了很多。那么,与jQuery比又如何呢?
从分析图中,我们可以看到,jQuery进行展示最简单的hello,world的应用比原生的纯javascript满了50毫秒,但是jQuery版本和原声版本都是React的3倍。
所以,很清晰,如果要说哪一个更快,原生的javascript和jQuery无疑略胜一筹。
但是,使用库总是要比不使用库慢一些,这显然是再正常不过了,在内存里进行构建DOM,然后再进行真实的DOM操作更慢,也是很符合逻辑的情况。
废话说多了,现在让我们准确思考一下,怎么使得虚拟DOM加载更快。
怎么使用虚拟DOM
我的"hello world"项目对于React来说是不公平的,原因在于他们仅仅处理的是初次渲染页面的性能比较。React设计的目的是用来更新网页。
因为虚拟DOM的存在,每一次数据模型的改变都会触发虚拟用户接口的刷新。这与其他库进行直接的DOM更新是不一样的。虚拟DOM实际上使用了更少的内训,因为它不需要在内存中设置观察者。
然而,每一次动作发生的时候,在内存中比较虚拟DOM也是低效的。这需要大量的CPU运算。
因为这个愿意,React开发者在决定需要渲染什么的时候并不是完全被动的。如果你知道特定的动作不会影响特定的组件,你可以告诉React不要去分析组件差别,这无疑可以大大节省资源,加快应用程序的性能。示范操作中的React程序是可以进行性能提升的。
真实情况是,没办法准确的知道虚拟DOM是否比直接进行DOM操作更快。因为这依赖于很多变量,尤其是和你怎么优化程序密切相关。
这并不是革命性或者令人惊讶的事情,每个人使用的 工具 都是挺好的。React和虚拟DOM给予我们的,是用一种简单的方式进行UI渲染,它提供给我们一种更加简便的方式来更新浏览器。这种简化可以大大释放我们的脑力负担,使得优化用户界面更加的容易。这才是React真正好处所在的地方,如果处理得到,使用React,兼具性能和生产力,何乐而不为呢?
原文地址: www.accelebrate.com/blog/the-re…
作者: Chris Minnick
说明:原文有一处举了一个100000个墨西哥玉米卷的例子,只是想说明不用每一次拿一个玉米卷,而是等待想拿的玉米卷确定之后然后在进行运输到自己国家进行消费。本质上还是映射React的工作方式,原文闲的稍加啰嗦,有删节。
总结: 本文核心有两点:1.稍微介绍一下React的虚拟DOM和原生DOM的区别和联系。2.文末点出,虚拟DOM如果处理得到,是可以处理好性能问题的,但是React的真正好处在于,它的模块化思想,释放了生产力。
颠覆:文中有几个观点需要重新审视,我们也经常听说直接操作DOM是低效的,但是这种低效在什么地方,似乎也没有国内的开发者进行准确的数据论证比较,作者给出了它的解释,直接操作DOM并不低效,低效的地方在于渲染页面的过程繁杂浪费时间,相比于React批处理之后只渲染一遍无疑是高效了很多。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
嵌入式系统开发之道
2011-12 / 69.00元
《嵌入式系统开发之道:菜鸟成长日志与项目经理的私房菜》用平易朴实的语言,以一个完整的嵌入式系统的开发流程为架构,通过一位“菜鸟”工程师与项目经理的诙谐对话,故事性地带出嵌入式系统概念及开发要素,并点出要成为一名称职的嵌入式系统工程师,在实际工作中所必须具备的各项知识及技能。 《嵌入式系统开发之道:菜鸟成长日志与项目经理的私房菜》可以分为三大部分:第1、3、4、17、18、19章和附录D为嵌入......一起来看看 《嵌入式系统开发之道》 这本书的介绍吧!