您的位置:首页 > Web前端 > JavaScript

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

2016-05-10 22:52 369 查看
http://www.cnblogs.com/ztfjs/p/domeach2.html

  序:在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和渲染树构建完成,浏览器就开始显示页面元素。

  参考  /article/7895030.html 详细阐述了【浏览器渲染原理】渲染树构建之渲染树和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标签");
});


更多关于事件委托 参考:/article/4837325.html js中的事件委托

3.dom篇总结

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

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

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

4.使用事件委托
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: