随着Ajax和RIA越来越成为主流,Javascript对事件(Event)的支持也得到了越来越多的关注。像雅虎这样的公司正在突破RIA的极限,让web应用程序在浏览器中更有效的运行,就像桌面应用程序一样。雅虎的邮箱应用就是一个很好的例子。
雅虎的一些工程师给我们展示了提高Javascript应用程序性能的技术。其中有提到强大的事件处理架构。提高性能的要旨就是用事件委托(Event Delegation)而非传统的事件处理(Event Handling)。
我发现一个问题是,网上大部分的例子是用YUI编写的,隐藏了背后的Javascript。在这边文章中,我会给出纯Javascript版本的事件代理的例子。
传统的Javascript事件处理和Unobtrusive Javascript
传统的Javascript时间处理并不是有效率的。一个强大的Ajax和RIA应用程序,它会有大量的用户交互接口。所有的这些用户交互接口会有一个对应的事件处理,所有的这些事件处理需要捆绑在一起才可以被用户触发。
如果用现今的技术,Unobtrusive scripting,这是一个将事件和脚本从(X)HTML中剥离的技术。它将访问DOM并通过content,presentation, behivor分离的技术来附加脚本到对象中。(X)HTML中再也不会出现onclick这样的时间处理代码。
在传统的Javascript中,把所有的事件捆绑在一起是有代价的。不仅是捆绑它们的步骤很多,而且重复的代码占用浏览器内存。不仅仅如此,如果你改变DOM,新添加的元素不会注意到onload事件,你需要重新设置事件。
请看下面的代码:
<ul id="listing"> <li><a href="#">Handlers Test</a></li> <li><a href="#">Handlers Test</a></li> <li><a href="#">Handlers Test</a></li> <li><a href="#">Handlers Test</a></li> </ul>
window.onload = function(){ var x = document.getElementById("listing"); x = x.getElementsByTagName("a"); for (var i = 0; i < x.length; i++){ (function(){ var z = i; x[i].onclick = function(){ alert("clicking" + z); return false; }; })(); } }
这段代码会查找里列表中所有的锚点,并给它们分别添加一个匿名函数。这很好的做到了unobtrusive。但是我们却在点击事件上消耗了大量的浏览器内存。你能想象如果一个更大的列表是什么样子吗?
合并所有的用户交互接口,你就会有类似下面的一个场景:
对象+事件,对象+事件,对象+事件... = 一个捆绑在一起的集合
事件委托(Event Delegation)和事件冒泡(Event Bubbling)
基本原理是通过
Javascript的事件委托和事件处理