《高性能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.使用事件委托
--------------学无止境,站在巨人的肩上才能看的更高、更远--------------