在JavaScript中,添加到页面上的事件处理程序数量直接关系到页面的整体运行性能,导致这个问题的原因有几个:
① 每个函数都是对象,都会占用内存,内存中的对象越多,性能就越差;
② 必须事先指定所有事件处理程序而导致的DOM访问次数,会延迟整个页面的交互就绪时间。
因此,必须利用好事件处理程序,才能提高JavaScript的性能。
解决Web应用程序内存和性能问题有两种方法:
① 采用事件委托
② 移除事件处理程序
1、事件委托:
对事件处理程序过多的问题的解决方案是事件委托,事件委托利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。使用事件委托,只需在DOM树中尽量最高的层次上添加一个事件处理程序。
var ul = document.getElemengtsByTagName("ul")[0];
EventUtil.addHandler(ul, "click", function(event) {
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
switch(target.id) {
case "id1":
alert("id1");
break;
case "id2":
alert("id2");
break;
case "id3":
alert("id3");
break;
}
}
当然,也可以为document对象添加一个事件处理程序,用以处理页面发生的某种特定类型的事件,这样的优点在于:
① document对象很快就能访问,而且可以在页面生命周期的任何时点为它添加事件处理程序而无需等待DOMContentLoaded或load事件;
② 在页面中设置事件处理程序所需的时间更少,只添加一个事件处理程序所需的DOM引用更少,所花的时间更少;
③ 整个页面占用的内存空间更少,能够提升整体性能。
最适合采用事件委托的事件包括:click,mousedown,mouseup,keydown,keyup,keypress。虽然mouseover和mouseout事件也冒泡,但适当处理它们不容易,而且经常需要计算元素的位置,因为当鼠标从一个元素移到其子节点时,或当鼠标移出该元素时,都会触发mouseout事件。
2、移除事件处理程序
在不需要的时候,移除事件处理程序,也是解决Web应用程序内存和性能问题的解决方案。
造成Web应用程序内存和性能问题的两种情况:
1) 从文档中移除带有事件处理程序的元素(可以通过纯粹的DOM操作,如removeChild()和replaceChild()方法,也可以是使用innerHTML替换页面中的某部分)时,原来添加到元素的事件处理程序极有可能无法被当做垃圾回收。
① 解决方法一:若事先知道某个元素即将被移除,那么最好手工移除事件处理程序。
② 解决方法二:采用事件委托,若事先知道将来有可能使用innerHTML替换页面中的某部分,就可以不直接把事件处理程序统计哀悼该部分的元素,而是通过把事件处理程序指定给较高层次的元素。
2) 卸载页面(可能是两个页面来回切换,也可能是单击了刷新按钮),内存中滞留的对象数目就会增加,因为事件处理程序占用的内存并没有被释放。
解决方法:在页面卸载之前,先通过onunload事件处理程序移除所有的事件处理程序,也就是说,只要是通过onload事件处理程序添加的东西,最后都要通过onunload事件处理程序将它们移除。
这体现出了事件委托的优势:需要跟踪的事件处理程序少,移除它们很容易。