优化你的DOM

优化DOM的本质其实就是减小DOM树的重流与重绘。对于重流和重绘的理解,详见《前端知识普及之HTML
优化DOM的结构,无非就是引用保存,动画优化,节点保存,更新节点等基本操做。
曾记得,之前在网上翻阅HTML的时候,不少人都会不约而同(儿童)的说道,获取到DOM节点后必定要记得保存。不然,下场很难看的。
为何~为何~为何~
咱们都知道所谓的js实际上是DOM,BOM,ECMA结合的产物。 原本我js挺快的,你非要去的DOM说说话。 那怎么办,只有敲敲门,等DOM来回应你呀~ 可是,这个等待时间灰常长。
看个demo吧.css

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等属性。
而这样作的原理就是减小重流和重绘的次数。html

重流重绘发生的状况

那重流和重绘一般什么状况下会发生呢?
重流发生状况:前端

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

  2. 元素位置改变数组

  3. 元素尺寸改变浏览器

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

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

  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

建立节点

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进行布局,脱离了文档流,防止页面过分的重排,赞~最后:优化之路漫漫,你们好自为之~

相关文章
相关标签/搜索