本文部分内容,引用自http://my.oschina.net/wanjubang/blog/543745
想要知道如何提高效率,那么首先我们需要知道,关于DOM的操作,哪一个最影响整体的效率,也就是说,哪一处所占用的时间较大,首先,我们介绍一下,HTML页面显示在浏览器中,都要经过哪些流程。
其中,第三步,对render tree的各个结点计算布局信息为时间占用较大的一部分,而在这一步中,包含了layout,layout操作,是对render tree中对象的大小、尺寸进行计算,在默认情况下,浏览器的layout为lazy模式,也就是说,并非每次我们对DOM进行修改时都会layout,而是将这些修改存储在一个队列中,在一定的情况下统一提交队列,进而实现layout操作。
在本文中,对于DOM操作效率的提高,针对于减少layout次数这一思路来进行。因此,我们要想方设法,延长DOM修改队列提交的间隔时间,尽量减少对DOM修改操作提交的次数。
当我们需要获取某一属性,这一属性需要计算才能得到并且,队列中存在尚未提交的DOM修改操作,则此时,DOM修改操作的队列将会被提交。举个栗子
<!--读取属性--> var h1 = element1 . clientHeight ; <!--将DOM修改操作放入队列--> element1 . style . height = ( h1 * 2 ) + 'px' ; <!--读取属性,同时提交队列中的操作--> var h2 = element2 . clientHeight ; <!--将DOM修改操作放入队列--> element2 . style . height = ( h2 * 2 ) + 'px' ; <!--读取属性,同时提交队列中的操作--> var h3 = element3 . clientHeight ; <!--将DOM修改操作放入队列--> element3 . style . height = ( h3 * 2 ) + 'px' ;在这里,由于clientHeight为需要计算的属性,当第二次读取属性时,由于队列中存在对DOM修改的操作,因此将队列中的操作提交,更新DOM tree,进而更新render tree。
为了提高效率,减少更新render tree的次数,可以先统一读取属性,然后统一修改DOM,这样,就可以减少更新render tree的次数,代码示例如下“:
<!--读取属性--> var h1 = element1 . clientHeight ; var h2 = element2 . clientHeight ; var h3 = element3 . clientHeight ; <!--将DOM修改操作放入队列--> element1 . style . height = ( h1 * 2 ) + 'px' ; element2 . style . height = ( h2 * 2 ) + 'px' ; element3 . style . height = ( h3 * 2 ) + 'px' ;
<!--创建一个虚拟节点--> var fragment = document . createDocumentFragment ( ) ; for ( var i = 0 ; i < items . length ; i ++ ) { <!--生成多个li标签,并将标签附加在虚拟结点上--> var item = document . createElement ( "li" ) ; item . appendChild ( document . createTextNode ( "Option " + i ) ; fragment . appendChild ( item ) ; } <!--将对该虚拟结点一次性提交给页面结构--> list . appendChild ( fragment ) ;