javascript性能优化(3)

DOM编程

1.文档对象模型(DOM)
访问的dom越多,代码的执行速度就越慢。
2.innerHtml和DOM方法

更改dom的时候,使用innerHTML(字符串拼接)和dom方法(document.createElement();document.createTextNode(););旧版本的浏览器如,IE6等innerHTML速度更快,反而新版的浏览器dom方法更快。总的来说,随着技术发展差异不大,具体使用哪种方法,还是与你个人的代码风格有关。

3.节点克隆

使用ele.cloneNode()克隆节点更有效率,但是提高的不多。

4.集合

遍历数组比遍历集合更快;如果需要遍历一个集合看业务是否需要将集合转换成数组;

    function toArray(coll) {
        for(var i=0,a=[],len=coll.length;i<len;i++){
            a[i]=coll[i];
        }
        return a;
    }

var coll=document.getElementsByTagName("div");这时候的length,每次访问都会导致集合更新,会在所有的浏览器上产生明显的性能损失。所以,将length放入到一个变量中len`。这样效率会更高。

一般来说对于,任何类型的dom访问,如果同一个dom属性或方法被访问一次以上,最好使用一个局部变量缓存此dom成员,当遍历一个集合时,第一个优化是将集合引用存储于局部变量,并在循环之外缓存length。然后,如果在循环中多次访问同一个集合元素,那么使用局部变量缓存他。见下面的代码

 //slow
    function collectin() {
        var coll = document.getElementsByTagName("div"),
            len = coll.length,
            name = "";
        for (var con = 0; con < len; con++) {
            name = document.getElementsByName("div")[con].nodeName;
            name = document.getElementsByName("div")[con].nodeType;
            name = document.getElementsByName("div")[con].tagName;
        }
        return name;
    }
    //faster
    function collectin() {
        var coll = document.getElementsByTagName("div"),
            len = coll.length,
            name = "",
            ele = null;
        for (var con = 0; con < len; con++) {
            ele=coll[con];
            name = ele.nodeName;
            name = ele.nodeType;
            name = ele.tagName;
        }
        return name;
    }

遍历childrenchildNodes更快。如果浏览器支持 document.querySelectorAll()
,那么最好使用它。

        document.querySelectorAll("div.warning div.notice")

dom重新排版和重绘代价昂贵,所以,提高程序响应速度好的方法是减少此类的操作,应该讲多个dom和风格改变合并到一个批次中一次性执行。

    var computed=document.defaultView.getComputedStyle(document.body,"");

修改css样式,可以使用更改css的类名的方法,而不修改内联样式,或者使用cssText

        ele.style.cssText="background-color: #f00;border: 1px solid #0f0;";

避免一个一个的修改元素的style,如:ele.style.padding="5px"

5.批量修改dom(渲染页面)

尽量最小数量的dom操作和重排版。在文档外创建一个文档片段,然后在把他添加到dom中;只引发一次排版,只触发一次“存在的dom”;
var frag=document.createDocumentFragment();
frag.appendChild(document.createElement("li"));
document.querySelector("#wrap").appendChild(frag);

createDocumentFragment的介绍
在一些简单的动画的时候,设置局部变量远比直接使用要优化的多;

6.将元素提出动画流

1.页面顶部可以“折叠/展开”的元素称为动画元素,用绝对坐标对它进行绝对定位,当他尺寸改变时,就不会推动页面其他元素的位置,而只是覆盖其他元素。
2.展开动作只在“动画元素”中进行,这时候其他元素的坐标并没发生改变,换句话说,其他元素并没有因为“动画元素”的扩大而随之下移,而是任由动画元素覆盖。
3.“动画元素”的动画结束时,将其他元素的动画移动到动画元素的下方,即元素重新定位,页面“跳”了一下。

7.事件托管

页面有大量元素,每个元素有一个或者多个事件句柄与之挂接(如onclick)时,无论怎样,你访问或者修改dom的节点时,程序就会变慢。
所以一个简单优雅的处理方式,是事件托管。他是基于这样的事实:事件逐层冒泡总能被父元素捕获。
每个事件的三个阶段:捕获->到达目标->冒泡。

    <div id="downLoad">Click Me!
        <a href="javascript:;">a-link</a>
        <p>p标签</p>
        <span>span</span>
    </div>
//*********************
   var odownLoad = document.getElementById("downLoad");
    odownLoad.onclick = function (e) {
        e=e||window.event;
        var target=e.target||e.srcElement;
        console.log(target.nodeName);//节点名称如 a标签 “A”,p-"P",div-"DIV";
        console.log(target.href);
        if(typeof e.preventDefault==="function"){ //阻止冒泡
            e.preventDefault();
            e.stopPropagation();
        }else {
            e.returnValue=false;
            e.cancelBubble;
        }
    }

总结

  • 最小化的dom访问,在javascript端做尽可能多的事。
  • 在反复访问的地方使用局部变量存放dom引用。
  • 小心的处理HTML集合,因为他们表现出“存在性”,总是对底层文档重新查询。将集合的length属性缓存到一个变量中,在迭代中使用这个变量。如果经常操作这个集合,可以将集合copy到数组中。
  • 如果可能的话,使用速度更快的API,如//querySelectorAll(); //querySelector()//fistElemnetChild;
  • 注意页面重绘和重排版;批量修改风格,离线操作dom树,缓存并减少对局部信息的访问。
  • 动画使用绝对定位,并使用拖放处理。
  • 使用时间托管来最小化时间句柄数量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值