查看原文
其他

优化你的DOM

2016-10-06 jimmy_thr 前端圈

优化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等属性。


而这样做的原理就是减少重流和重绘的次数。

重流重绘发生的情况

那重流和重绘通常什么情况下会发生呢?重流发生情况:

  1. 添加或者删除可见的DOM元素

  2. 元素位置改变

  3. 元素尺寸改变

  4. 元素内容改变(例如:一个文本被另一个不同尺寸的图片替代)

  5. 页面渲染初始化(这个无法避免)

  6. 浏览器窗口尺寸改变

总的来说,就是改变页面的布局,大小,都会发生重流的情况。那重绘什么时候会发生呢? 发生重流就一定会发生重绘,但是,重绘的范围比重流稍微大了一点。比如,当你仅仅改变字体颜色,页面背景颜色等 比较"肤浅"的操作时,是不会打扰到重排的。

合并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

1、创建节点

var div = document.createELement("div");

2、查找节点

var divs = document.querySelectorAll('div');
//很多个,放在数组内
var onlydiv = document.querySelector('div');
//只有一个
//以及document.getElement系列

3、查看节点

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");
//....

4、移动节点

ele.replaceChild(replace,replaced);
//replace代替replaced
//添加子节点
ele.appendChild(child);
//删除子节点
ele.removeChild(child);
//插入子节点
ele.insertBefore(newEle,referenceEle);

Ok~ 其实,上面所说的这些API只要涉及到DOM操作的都会发生重排。所以,这里是地方可以优化的.

5、使用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进行布局,脱离了文档流,防止页面过度的重排,赞~
最后:


优化之路漫漫,大家好自为之~



【第二期读书会送书活动正在进行中】

一、[活动]《CSS揭秘》签名版等您拿,第二期读书会来啦!


【您可能感兴趣的文章】

一、你所不知道的 URL

二、Git学习之路

三、[React启蒙系列]理解React 组件

四、探知JS测试(1)

五、探知JS测试(2)

六、前端学习路径加强版——来自《前端养成记》

七、前端技能图谱

八、重构代码的tricks

九、Google老板带人的3种方法

十、Sass 与 Compass 实战经验总结



前端圈--打造专业的前端技术会议

为web前端开发者提供技术分享和交流的平台

打造一个良好的前端圈生态,推动web标准化的发展

官网:http://fequan.com

微博:fequancom | QQ群:41378087


长按二维码关注我们

投稿:content@fequan.com

赞助合作:apply@fequan.com

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存