《高性能javascript》 领悟随笔之-------DOM编程篇(二)

《高性能javascript》 领悟随笔之-------DOM编程篇二

  序:在javaSctipt中,ECMASCRIPT规定了它的语法,BOM实现了页面与浏览器的交互,而DOM则承载着整个页面文档。DOM编程性能一直以来都是非常受开发者关注的话题,如何编写高性能的DOM是前端开发必不可少的技能。


 1.重绘与重排

  当浏览器加载完页面所有的元素、js、css、图片之后会自动生成两个数据结构:

1.dom树

(图片为转载)

如图所示,dom树表示了整个页面文档的结构,通过访问dom树我们可以得到某个元素,并且操作这个元素;

2.渲染树

  表示dom节点如何显示;

《高性能javascript》一书中是这么描述的:dom树中每一个需要显示的节点在渲染树中至少存在一个对应的节点(隐藏的dom元素在渲染树中没有对应的节点)。渲染树中的节点被称为 “帧(frams)” 或 “盒(boxes)”,符合css模型的定义,理解页面元素为一个具有内边距(padding),外边距(margins),边框(borders)和位置(position)的盒子。一旦dom和渲染树构建完成,浏览器就开始显示页面元素。

  参考  http://blog.csdn.net/greenqingqingws/article/details/19822139  详细阐述了【浏览器渲染原理】渲染树构建之渲染树和DOM树的关系;

 

当我们去修改元素的属性,比如宽度、高度、动态增加文字、就会引起浏览器的“重排 与 重绘”,减少它发生的次数是提高dom性能的关键之一;

 

那么如何减少 “重排 与 重绘” 发生的次数呢?

3.合并多次对dom和样式的修改,然后一次性处理掉;

一个栗子:

 

var el = document.getElementById('mydiv');
el.style.color='red';
el.style.padding='5px';
el.style.borderLeft = "1px solid red";

 

这个栗子中div有三个元素样式的改变,每一个都会影响元素的结构,这种情况会导致在某些浏览器下页面触发三次重排,这么做效率是非常低下的;

将css集中修改:csstext 方法,它可以以字符串的形式一次性修改css样式信息,需要注意的是它会覆盖已存在的行间样式信息;

一个栗子:

var el = document.getElementById('mydiv');
var csstext = "color:red;border-right:1px solid red;padding:5px;";


//集中一次性修改样式 
el.style.cssText += csstext;

还可以使用添加删除class名称达到同样的效果,通过class名得到的性能会更好,在不同的应用场景应首先考虑增删class名的修改方法;

4.批量修改dom;

 

当我们通过ajax请求得到一个列表数据的时候,我们需要循环将数据插入到页面中。如果每次循环插入一个节点的话,那页面很可能会直接崩溃掉,我们要避免这个问题的发生;

文档片段(document.createDocumentFragment());

创建一个隐式的副本,看栗子

 

//创建一个fragment临时dom存储空间
var fragment= document.createDocumentFragment();

for(......){
 var div =  document.createElement("div");
........
//将div存储在fragment临时空间中
          fragment.appendChild(div);
}
//将组装好的dom塞进body
document.body.appendChild(fragment);

 

此方法只插入一次,完成所有的dom更新工作,是dom操作性能的关键之一  (innerHTML同理)

 

                                   

2.事件委托

每多绑定一个事件处理程序都会加重页面的性能负担,简单优雅的操作应该使用 “事件委托”。 它基于事件冒泡机制;通过监听父级元素的事件,判断出事件的来源元素;

当我们点击div,div触发click事件,事件被冒泡到body body触发click事件直到文档根document;

假如要给页面中的每一个a元素添加一个点击事件,我们可以这样做:

document.addEventListener("click",function(ev){
        var Event = ev||window.event;
        if(Event.target.nodeName=="A"){
            alert("点击了a标签");
        }
    },false);

当a点击被冒泡到document的时候,判断它的来源,如果是a则执行相应的代码,这就是事件委托的概念

在jQuery中事件冒泡被封装在.on()方法里 , 可以更简单的使用它:

$(document).on("click","a",function(){
        alert("这是一个a标签");
 });

更多关于事件委托  参考:http://www.cnblogs.com/leejersey/p/3801452.html  js中的事件委托

3.dom篇总结

1.最小化访问dom的次数,尽可能使用javascript处理;

2.如果多次访问一个dom节点,需要保存局部变量中;

3.处理html集合最好的方法是将他们复制到一个临时的数组中,数组的访问速度要比dom快的多;

4.使用事件委托

--------------学无止境,站在巨人的肩上才能看的更高、更远--------------

 

原文地址:https://www.cnblogs.com/ztfjs/p/domeach2.html