性能优化思考
优化由来
<!DOCTYPE html>
<html>
<head>
<title>TODO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script>
window.onload = function(){
var lis = document.getElementsByTagName('li')
var list = Array.prototype.map.call(lis, function(el){
return {dom: el, text: el.textContent}
})
console.log(list)
var newList = list.concat().reverse()
diff(list, newList)
//编写一个diff方法,让LI元素也跟着倒过来排列
}
</script>
</head>
<body>
<div ms-controller='for1'>
<ul>
<li>111</li>
<li>222</li>
<li>222</li>
<li>111</li>
<li>333</li>
</ul>
</div>
</body>
</html>
三种方法
function diff1(list, newList) {
document.createDocumentFragment();
var len = newList.length;
var parentEle = list[0].dom.parentElement;
var refEle;
refEle = list[0].dom;
list.forEach(function(ele,i){
parentEle.insertBefore( newList[i].dom, refEle);
})
}
function diff2(list, newList) {
var frg = document.createDocumentFragment();
var container = list[0].dom.parentElement;
newList.forEach(function(ele){
frg.appendChild(ele.dom)
})
container.appendChild( frg );
}
function diff3(list, newList) {
var frg = document.createDocumentFragment();
var container = list[0].dom.parentElement;
newList.forEach(function(ele){
var li = document.createElement('li');
li.innerText = ele.text;
frg.appendChild(li)
})
container.innerHTML = '';
container.appendChild( frg );
}
方法思路
diff1:
简单粗暴,把倒序的DOM逐个插入在第一个LI之前。
diff2:
用documentFragment做了优化,目的是减少reflow
diff3:
第三种,取自虚拟dom的想法,其实多了一步创建DOM元素的
测试结果
diff1: 821.597ms
diff2: 1366.079ms
diff3: 3213.761ms
结果分析
第二种比第三种快,原因是重新创建dom的开销。
第一种比第二种快,就有点想不通了。documentFragment的目的不就是减少reflow吗。猜想chrome做 了优化
documentFragment
MDN
documentFragment是DOM节点,他不是DOM树的节点。一般的用法是:创建文档片段、追加元素到文档片段然后把文档片段插入到DOM树中。在DOM树中,文档片段被文档的子节点替换。
因为,documentFragment在内存中,操作documentFragment不会导致页面reflow. 因此,有助于性能的提高。
john关于文档片段的研究,不过研究的浏览器都比较老
google的性能优化建议