文章主要是对于一个很容易被忽略的知识点:createDocumentFragment()方法的一个复习,并给大家解锁一个解决给某个标签动态改变其子节点顺序的新姿势.
首先,documentFragment是一个很早之前就被广泛支持的方法,所以犀牛书上面所提供的为element对象增加一个原型方法insertAdjacentHTML()的兼容性写法,大家可以无视了,因为IE7-IE9都亲测完美支持.当然,如果你想碰IE6,就当我没说.
关于性能
其实createDocumentFragment()这个方法创建的目的,就是把它当做一个特殊的node,作为其他节点的一个临时的容器.
也就是说,当我们需要使用JS为某标签动态插入较多的子节点的时候,我们可以将需要插入的节点组成一个节点树.然后在插入的时候直接把这个节点树一次性插入到文档流中.
相比于每生成一次节点之后马上插入文档流的做法来说,使用createDocumentFragment()方法可以大大减少浏览器的重绘次数,从而能够提升性能.(每当我们进行动态插入节点的时候,都会引起浏览器的一次重绘操作)
有一点要特别注意的是,IE浏览器是例外的,因为IE浏览器的特殊性,导致当我们使用createDocumentFragment()方法进行动态插入时,反倒会降低浏览器的性能.
某节点子节点的倒序排列的JS实现
了解到createDocumentFragment()这个方法其实这个问题就很简单了.先将源文档的lastChild逐个插入到createDocumentFragment()的节点树中即可.
1 | function reverse(n){ |
有一点需要大家特别注意的是,当我们不使用a这个局部变量而是直接使用n.childNodes.length,每次for循环都进行重新判定的时候,会发生神奇的现象.n.childNodes.length会离奇般的消失了一半.
其实了解现代浏览器的childNodes.length判定机制的同学都会知道,当我们对文档流进行childNodes判定的时候,其实其子标签两边的空格和回车也是会作为文本节点被算进childNodes.length里面的.
1 | <ul id="aUl"> |
说到这里其实刚刚说的神奇的现象就很好解释了,因为我们从后面开始进行移动元素”空白文本节点”及li标签的时候,它们的空白节点会动态消失.所以我们使用for循环每次进行判定该文档的长度的时候,以上面的文档结构为例,判定长度为11,但实际上循环次数仅5次.
这个坑很好的教了我们,要将长度判定等拿到for循环外面的重要性啊,不仅能提升性能,还能避免踩坑…
以上.