探究React虚拟DOM
Posted 2bit潮学
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了探究React虚拟DOM相关的知识,希望对你有一定的参考价值。
关注 入坑互联网 ,回复“加群”
什么是虚拟DOM
React将DOM抽象为虚拟DOM, 然后通过新旧虚拟DOM 这两个对象的差异(Diff算法),最终只把变化的部分重新渲染,提高渲染效率的过程;
为什么使用虚拟DOM
在传统的 Web 应用中,我们往往会把数据的变化实时地更新到用户界面中,于是每次数据的微小变动都会引起 DOM 树的重新渲染。
虚拟DOM的目的是将所有操作累加起来,统计计算出所有的变化后,统一更新一次DOM。
为什么虚拟DOM会比DOM更优
当创建一个元素比如div,这个元素上本身或者继承很多属性如 width、height、offsetHeight、style、title,另外还需要注册这个元素的诸多方法,比如onfucos、onclick等等。这还只是一个元素,如果元素比较多的时候,还涉及到嵌套,那么元素的属性和方法等等就会很多,效率很低。
这个元素会挂载默认的styles、得到这个元素的computed属性、注册相应的Event Listener、DOM Breakpoints以及大量的properties,这些属性、方法的注册肯定是需要h耗费大量时间的。
尤其是在js操作DOM的过程中,不仅有dom本身的繁重,js的操作也需要浪费时间,我们认为js和DOM之间有一座桥,如果你频繁的在桥两边走动,显然效率是很低的。
React的虚拟DOM就是解决这个问题的!虽然它解决不了DOM自身的繁重,但是虚拟DOM可以对javascript操作DOM这一部分内容进行优化。
来看下面这个最简单的例子,你就明白了:
比如说,现在你有一个列表是这样:
<ul>
<li>0</li>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
你希望变成下面这样:
<ul>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ul>
通常先把0, 1,2,3这些Element删掉,然后加几个新的Element 6,7,8,9,10进去,这里面就有4次Element删除,5次Element添加。共计9次DOM操作。
那React的虚拟DOM可以怎么做呢?
而React会把这两个做一下Diff,然后发现其实不用删除0,1,2,3,而是可以直接改innerhtml,然后只需要添加一个Element(10)就行了,这样就是4次innerHTML操作加1个Element添加。共计5此操作,这样效率的提升是非常可观的。
虚拟DOM和DOM之间的关系
首先,Virtual DOM并没有完全实现DOM,即虚拟DOM和真正地DOM是不一样的,Virtual DOM最主要的还是保留了Element之间的层次关系和一些基本属性。因为真实DOM实在是太复杂,一个空的Element都复杂得能让你崩溃,并且几乎所有内容我根本不关心好吗。所以Virtual DOM里每一个Element实际上只有几个属性,即最重要的,最为有用的,并且没有那么多乱七八糟的引用,比如一些注册的属性和函数啊,这些都是默认的,创建虚拟DOM进行diff的过程中大家都一致,是不需要进行比对的。所以哪怕是直接把Virtual DOM删了,根据新传进来的数据重新创建一个新的Virtual DOM出来都非常非常非常快。(每一个component的render函数就是在做这个事情,给新的virtual dom提供input)。
所以,引入了Virtual DOM之后,React是这么干的:你给我一个数据,我根据这个数据生成一个全新的Virtual DOM,然后跟我上一次生成的Virtual DOM去 diff,得到一个Patch,然后把这个Patch打到浏览器的DOM上去。完事。并且这里的patch显然不是完整的虚拟DOM,而是新的虚拟DOM和上一次的虚拟DOM经过diff后的差异化的部分。
虚拟DOM是怎么工作的?
与真实DOM相似,虚拟DOM也是节点树,以对象的形式列出内容,属性。React的render方法从React组建中创建节点树,因为动作改变等引起数据模型变化的时候,React更新节点树。
每次React app内部的数据改变,用户界面的虚拟DOM都会构建。
这里就是最有趣的地方,在React中更新浏览器DOM需要三步:
-
每次数据模型变化的时候,虚拟DOM节点树都会重新构建。
-
React依赖某个算法(称之为diff算法)来与上一个虚拟DOM节点数进行比较,只有在不同的情况下才重新进行计算。
3.所有的变化要经过批处理,完成之后,真实DOM才进行更新。
过程如下图:
虚拟DOM慢吗?
有人认为只要有一点改变就重新构造整个虚拟DOM节点树有点浪费,但是他没有提及一个事实,React在内存中存储有两个虚拟DOM树。
但是,真实情况是渲染虚拟DOM总是比直接渲染浏览器DOM快。这种论断与你使用的浏览器也没多大的关系。
最后,我们来说一下为什么Virtual Dom快
由于每次生成virtual dom很快,diff生成patch也比较快,而在对DOM进行patch的时候,虽然DOM的变更比较慢,但是React能够根据Patch的内容,优化一部分DOM操作.
重点就在最后,哪怕是我生成了virtual dom(需要耗费时间),哪怕是我跑了diff(还需要花时间),但是我根据patch简化了那些DOM操作省下来的时间依然很可观(这个就是时间差的问题了,即节省下来的时间 > 生成 virtual dom的时间 + diff时间)。所以总体上来说,还是比较快。
以上是关于探究React虚拟DOM的主要内容,如果未能解决你的问题,请参考以下文章