实现某节点子节点的倒序排列

文章主要是对于一个很容易被忽略的知识点:createDocumentFragment()方法的一个复习,并给大家解锁一个解决给某个标签动态改变其子节点顺序的新姿势.

首先,documentFragment是一个很早之前就被广泛支持的方法,所以犀牛书上面所提供的为element对象增加一个原型方法insertAdjacentHTML()的兼容性写法,大家可以无视了,因为IE7-IE9都亲测完美支持.当然,如果你想碰IE6,就当我没说.

关于性能

其实createDocumentFragment()这个方法创建的目的,就是把它当做一个特殊的node,作为其他节点的一个临时的容器.

也就是说,当我们需要使用JS为某标签动态插入较多的子节点的时候,我们可以将需要插入的节点组成一个节点树.然后在插入的时候直接把这个节点树一次性插入到文档流中.

相比于每生成一次节点之后马上插入文档流的做法来说,使用createDocumentFragment()方法可以大大减少浏览器的重绘次数,从而能够提升性能.(每当我们进行动态插入节点的时候,都会引起浏览器的一次重绘操作)

有一点要特别注意的是,IE浏览器是例外的,因为IE浏览器的特殊性,导致当我们使用createDocumentFragment()方法进行动态插入时,反倒会降低浏览器的性能.

某节点子节点的倒序排列的JS实现

了解到createDocumentFragment()这个方法其实这个问题就很简单了.先将源文档的lastChild逐个插入到createDocumentFragment()的节点树中即可.

1
2
3
4
5
6
7
8
function reverse(n){
var f = document.createDocumentFragment();
var a = n.childNodes.length
for (var i = 0; i < a; i++) {
f.appendChild(n.lastChild)
}
console.log(f)
}

有一点需要大家特别注意的是,当我们不使用a这个局部变量而是直接使用n.childNodes.length,每次for循环都进行重新判定的时候,会发生神奇的现象.n.childNodes.length会离奇般的消失了一半.

其实了解现代浏览器的childNodes.length判定机制的同学都会知道,当我们对文档流进行childNodes判定的时候,其实其子标签两边的空格和回车也是会作为文本节点被算进childNodes.length里面的.

1
2
3
4
5
6
7
8
<ul id="aUl">
<li>1111</li>
<li>2222</li>
<li>3333</li>
<li>4444</li>
<li>5555</li>
</ul>
//当我们打印aUl中的子节点的长度时候,判定结果是11.(IE老版本会出现仅显示长度为5的问题,后面已经更正)

说到这里其实刚刚说的神奇的现象就很好解释了,因为我们从后面开始进行移动元素”空白文本节点”及li标签的时候,它们的空白节点会动态消失.所以我们使用for循环每次进行判定该文档的长度的时候,以上面的文档结构为例,判定长度为11,但实际上循环次数仅5次.

这个坑很好的教了我们,要将长度判定等拿到for循环外面的重要性啊,不仅能提升性能,还能避免踩坑…

以上.

文章目录
  1. 1. 关于性能
  2. 2. 某节点子节点的倒序排列的JS实现
|