如何能做出高效的web前端程序是我每次做前端开发都会不自觉去考虑的问题。几年前雅虎里牛逼的前端工程师们出了一本关于提升web前端性能的书籍,轰动了整个web开发技术界,让神秘的web前端优化问题成为了大街的白菜,web前端优化变成了菜鸟和大牛都能回答的简单问题,当整个业界都知道了惊天秘密的答案,那么现有的优化技术已经不能对你开发的网站产生的质的飞越,为了让我们开发的网站性能比别人的网站更加优秀,我们需要更加深入的独立思考,储备更加优秀的技能。
Javascript里的事件系统是我想到的第一个突破点。为什么会是javascript的事件系统呢?我们都知道web前端包含三个技术:html、css和javascript,html和css如何结合真是一目了然:style、class、id以及html标签,这个没啥好讲的,但是javascript是如何切入到html和css中间,让三者融合呢?最后我发现这个切入点就是javascript的事件系统,不管我们写多长多复杂的javascript代码,最终都是通过事件系统体现在html和css上,因此我就在想既然事件系统是三者融合的切入点,那么一个页面里,特别是当今越来越复杂的网页里必然会有大量事件操作,没有这些事件我们精心编写的javascript代码只有刀枪入库,英雄无用武之地了。既然页面会存在大量事件函数,那么我们按习惯写事件函数,会存在影响效率的问题吗?我研究下来的答案是真有效率问题,而且还是严重的效率问题。
为了说清楚我的答案,我要先详细讲解下javascript的事件系统。
事件系统是javascript和html以及css融合的切入点,这个切人点好比java里的main函数,一切神奇都是由这里开始,那么浏览器是如何完成这种切入呢?我研究下来一共有3种方式,它们分别是:
[b]方式一:html事件处理[/b]
html事件处理就是将事件函数直接写在html标签里,因为这种写法和html标签紧耦合,所以称为html事件处理。例如下面代码:
[url=#]
document.addEventListener("click",function(evt){
var target = evt.target;
switch(target.id){
case "btn":
alert("button");
break;
case "aa":
alert("a");
break;
}
},false);
运行之,我们发现效果和我们单独写按钮事件一样。但是它的好处是不言而喻的,一个函数搞定了整个页面的事件函数,而且没有事件函数被空闲,简直完美,这个方案还有个专业名称:事件委托。jQuery的delegate方法就是按这个原理做的。其实事件委托的效率不仅仅体现在事件函数的减少,它还能减少dom遍历操作,例如上面例子里我们在document上添加函数,document是页面里的顶层对象,读取它的效率是很高的,到了具体的对象事件我们也没有通过dom操作而是使用事件对象的target属性,所有这些只能用一句话概括:真是快,没理由的快。
事件委托还能给我们带来一个很棒副产品,使用过jQuery的朋友都应该用过live方法,live方法特点是你可以为页面元素添加事件操作,哪怕这个元素目前在页面还不存在,你也可以添加它的事件,理解了事件委托机制,live的原理就很好理解了,其实jQuery的live就是通过事件委托做的,同时live还是一种高效的事件添加方式。
理解了事件委托,我们会发现jQuery的bind方法是个低效的方法,因为它使用原始的事件定义方式,所以bind我们要慎用,其实jQuery的开发者也注意到这个问题,新版的jQuery里都有一个on方法,on方法包含了bind、live和delegate方法所有功能,所以我建议看了本文的朋友要摒弃以前使用添加事件的方式,多使用on函数添加事件。
事件委托还有个好处,上文里事件委托的例子我是在document上添加事件,这里我要做个比较,在jQuery里我们习惯把DOM元素事件的定义放在ready方法里,如下所示:
$(document).ready(function(){
XXX.bind("click",function(){});
});
ready函数是在页面DOM文档加载完毕后执行,它比onload函数先执行,这种提前好处很多,好处之一也是带来性能提升,jQuery这种事件定义也算是个标准做法,我相信有些朋友一定又把某些事件绑定放在ready外面,最后发现按钮会无效,这种无效场景有时一刹那,过会儿就好了,所以我们常常忽视了该问题的原理,不在ready函数绑定事件,这个操作其实是在DOM加载完毕之前绑定事件,而这个时间段下,很有可能某些元素还没在页面构造好,所以事件绑定会出现无效情况,因此ready定义事件的道理就是保证页面所有元素加载完毕后在定义DOM元素的事件,但是使用事件委托时可以避免问题的发生,例如将事件绑定在document,document代表整个页面,所以它加载完毕的时间可谓最早,所以在document上实现事件委托,就很难发生事件无效的情况,也很难发生浏览器报出“XXX函数未定义”的问题了。总结一下这个特点:事件委托代码可以运行在页面加载的任何阶段,这点对提升网页性能还是增强网页效果上都会给开发人员提供更大自由度。
好了本文写毕。晚安。