createDocumentFragment()用法总结
定义
createDocumentFragment()方法,是用来创建一个虚拟的节点对象,或者说用来创建文档碎片节点。可以包含各种类型的节点,在创建之初是空的。
使用场景
DocumentFragment节点不属于文档树,继承的parentNode属性总是null。它有一个很实用的特点,当请求把一个DocumentFragment节点插入文档树时,插入的不是DocumentFragment本身,而是它的所有子孙节点,即插入的是括号里的节点。它还有利于实现文档的剪切、复制和粘贴操作
另外,当需要添加多个dom元素时,如果先将这些元素添加到DocumentFragment中,再统一将DocumentFragment添加到页面,会减少页面渲染dom的次数,效率会明显提升。
appendChild
如果使用appendChild方法将原dom树中的节点添加到DocumentFragment中时,会删除原来的节点。
createDocumentFragment()和createElement()的区别:
1. 需要很多的插入操作和改动,继续使用类似于下面的代码则会很有问题
var ul = document.getElementById("ul");
for (var i = 0; i < 20; i++) {
var li = document.createElement("li");
li.innerHTML = "index: " + i;
ul.appendChild(li);
}
由于每一次对文档的插入都会引起重新渲染(计算元素的尺寸、背景显示、内容等),所以进行多次插入操作使得浏览器发生了很多此渲染,效率较低。这时我们提倡通过减少页面的渲染来提高DOM操作的效率的原因。一个优化的方法是将要创建的元素写到一个字符串上,然后一次性写到innerHTML上,这种利用浏览器对innerHTML的解析确实是相对上面的多次插入快了很多,但是构造字符串灵活性比较差,很难符合创建各种各样的DOM元素的需求,利用DocumentFragment可以弥补这两个不足
因为文档片段存在内存中,并不在DOM中,所以将子元素插入到文档片段中是不会引起页面回流(对元素位置和几何上的计算),因此使用DocumentFragment可以起到性能优化的作用。例如上面的代码就可以改成下面的片段
var ul = document.getElementById("ul");
var fragment = document.createDocumentFragment();
for (var i = 0; i < 20; i ++ ) {
var li = document.createElement("li");
li.innerHTML = "index:" + i;
fragment.appendChild(li)
}
ul.appendChild(fragment)
2. innerHTML
createElement创建的元素可以使用innerHTML,createDocumentFragment创建的元素使用innerHTML并不能达到预期修改文档内容的效果,只是作为一个属性而已。两者的节点类型完全不同,createElement创建的是元素节点,节点类型为1,createDocumentFragment创建的元素在文档中没有对应的标记,因此在页面上只能在js中访问到。
<div id="outer"></div>
<input type="button" value="createElement" id="btn_1"/>
<input type="button" value="createDocumentFragment" id="btn_2"/>
<script type="text/javascript">
var fragment_1 = document.createDocumentFragment();
fragment_1.innerHTML = '<p>我是一个粉刷匠</p>';
document.body.appendChild(fragment_1);
var fragment_2 = document.createElement('p');
fragment_2.innerHTML = '粉刷本领强';
document.body.appendChild(fragment_2);
</script>
3. 重复操作
createElement创建的元素可以重复操作,添加之后就算从文档里面移除依旧归文档所有,可以继续操作,但是createDocumentFragment创建的元素是一次性的,添加之后无法再操作了(说明:这里的添加并不是添加了新创建的片段,因为上面说过,新创建的片段在文档内是没有对应的标签的,这里添加的片段是所有子节点)
<div id="outer"></div>
<input type="button" value="createElement" id="btn_1" />
<input type="button" value="createDocumentFragment" id="btn_2" />
<script type="text/javascript">
function $(id) {
return document.getElementById(id);
}
var outer = $("outer");
var inner = $('inner');
$('btn_1').onclick = function(){
var div = document.createElement('div');
div.innerHTML = '<p>测试createElement</p>';
document.body.appendChild(div);
setTimeout(function(){
outer.appendChild(div);
setTimeout(function(){
outer.removeChild(div);
},1000)
},1000)
}
$('btn_2').onclick = function(){
var p = document.createElement('p');
p.innerHTML = '测试DocumentFragment';
var fragment = document.createDocumentFragment();
fragment.appendChild(p);
fragment.innerHTML = '<p>测试DocumentFragment</p>';
fragment.innerHTML = '<span>测试学习DocumentFragment</span>';
document.body.appendChild(fragment);
setTimeout(function(){
outer.appendChild(fragment);//报错,因为此时文档内部已经能够不存在fragment了
setTimeout(function(){
outer.removeChild(fragment);
},1000)
},1000)
}
</script>