优化DOM的实质实在就是削减DOM树的重流与重绘。关于重流和重绘的明白,详见《前端学问提高之HTML》
优化DOM的构造,不过就是援用保留,动画优化,节点保留,更新节点等基础操纵。
曾记得,之前在网上翻阅HTML的时刻,很多人都邑不谋而合(儿童)的说道,获取到DOM节点后一定要记得保留。不然,下场很丢脸的。
为何~为何~为何~
我们都晓得所谓的js实际上是DOM,BOM,ECMA连系的产品。 原本我js挺快的,你非要去的DOM说说话。 那怎么办,只需敲拍门,等DOM来回应你呀~ 然则,这个等待时候灰常长。
看个demo吧.
var times=10000;
var time1 = function(){
var time = times;
while(time--){ //DOM的两个操纵放在轮回内
var dom = document.querySelector("#Div1");
dom.innerHTML+="a";
}
};
var time2=function(){
var time = times,
dom = document.querySelector("#Div1");
while(time--){ //DOM的一个操纵放在轮回内
dom.innerHTML+="a";
}
};
var time3=function(){
var time = times,
dom = document.querySelector("#Div1"),
str = "";
while(time--){ //轮回内不安排DOM的操纵
str +="a";
}
dom.innerHTML=str;
}
console.time(1); //设置时候出发点
time1();
console.timeEnd(1);
console.time(2); //设置时候出发点
time2();
console.timeEnd(2);
console.time(3); //设置时候出发点
time3();
console.timeEnd(3);
//测试效果为:
1: 101.868ms
2: 101.560ms
3: 13.615ms
固然,这只是个比较夸大的例子了,当你过量的频仍操纵DOM的时刻,一定要记得保留。 而且,保留一定是要保留一切触及DOM相干的操纵。
比方. style,innerHTML等属性。
而如许做的道理就是削减重流和重绘的次数。
重流重绘发作的状况
那重流和重绘一般什么状况下会发作呢?
重流发作状况:
增加或许删除可见的DOM元素
元素位置转变
元素尺寸转变
元素内容转变(比方:一个文本被另一个差别尺寸的图片替换)
页面衬着初始化(这个没法防备)
浏览器窗口尺寸转变
总的来说,就是转变页面的规划,大小,都邑发作重流的状况。
那重绘什么时刻会发作呢? 发作重流就一定会发作重绘,然则,重绘的局限比重流轻微大了一点。比方,当你仅仅转变字体色彩,页面背景色彩等 比较”浅薄”的操纵时,是不会打扰到重排的。
兼并DOM的操纵
当我们如许操纵时:
div.style.color="red";
div.style.border="1px solid red";
浏览器会很智慧的将两次重排兼并到一次发作,节约资本。 实在函数撙节的头脑和这个有殊途同归的妙处
var throttle = (function(){
var time;
return function(fn,context){
clearTimeout(time); //举行函数的撙节
time = setTimeout(fn.bind(context),200);
}
})()
这个技能一般用在你调解浏览器大小的时刻。
然则,假如中心,你访问了offsetTop,clientTop等 马上实行属性的话。那效果你就么么哒了。
div.style.color="red"; //积聚一次重排纪录
var height = div.clientHeight; //触发重排
div.style.border="1px solid red"; //再次积聚一次重排
这时刻,浏览器已被你玩傻了。 所以,给的一点发起就是,假如要变动DOM构造最好一次性整完,或许,要整一起整~
我们上面的css修正,还能够如许
div.style.cssText="color:red;border:1px solid red"; //掩盖本来的css
div.classList.add("change"); //应用class来团体修改
DOM操纵的优化
DOM的操纵不过就CRUD。
这里简单说一下基础的API
建立节点
var div = document.createELement("div");
查找节点
var divs = document.querySelectorAll('div'); //很多个,放在数组内
var onlydiv = document.querySelector('div'); //只需一个
//以及document.getElement系列
检察节点
var html = div.innerHTML;
var outer = div.outerHTML; //这两个黑白常经常运用的
var classNames = div.classList;
var className = div.className;
var tagName = div.tagName;
var id = div.id;
var style = div.getAttribute("style");
//....
挪动节点
ele.replaceChild(replace,replaced); //replace替代replaced
//增加子节点
ele.appendChild(child);
//删除子节点
ele.removeChild(child);
//插进去子节点
ele.insertBefore(newEle,referenceEle);
Ok~ 实在,上面所说的这些API只需触及到DOM操纵的都邑发作重排。所以,这里是处所能够优化的.
运用fragment
当我们须要批量到场子节点的时刻,就须要运用fragment这个假造片段,来作为一个容器.
比方,我们须要在div内里增加100个p标签
var times = 100;
var addP = function(){
var time = times,
tag1 = document.querySelector('#tag1');
while (time--) {
var p = document.createElement('p');
tag1.appendChild(p);
}
}
var useFrag = function(){
var time = times,
tag1 = document.querySelector('#tag1'),
frag = document.createDocumentFragment();
while (time--) {
var p = document.createElement('p');
frag.appendChild(p);
}
tag1.appendChild(frag);
}
console.time(1);
addP();
console.timeEnd(1);
console.time(2);
useFrag();
console.timeEnd(2);
//基础事宜差为:
1: 1.352ms
2: 0.685ms
除了运用fragment片段,还能够运用innerHTML,outerHTML举行相干的优化操纵。这里就不赘述了
UI操纵的优化
这里想说的实在不多,就是学会运用absolute排版。 由于当你举行相干UI操纵的时刻,毫无疑问有能够不经意间,致使全屏的衬着。比方校园二手街的规划,当你下滑的时刻,他的headerbar便会发作扩展,规划较差的状况是整版重排。(傻逼傻逼傻逼)
他这里不一样,他直接运用absolute举行规划,脱离了文档流,防备页面过分的重排,赞~
末了:
优化之路漫漫,人人好自为之~