事件委派
Web应用都是由事件驱动运转的。我喜欢事件处理,尤其喜欢自己定义事件。它能使你的产品可扩展,而不用改动核心代码。有一个很大的问题(也可以说是功能强大的表现),是关于页面上事件的移除问题。你可以对某个元素安装一个事件监听器,事件监听器就开始运转工作。但页面上没有任何指示说明这有个监听器。因为这种不可表现的问题(这尤其让一些新手头疼),以及像IE6这样的”浏览器“在太多的使用事件监听时会出现各种的内存问题,你不得不承认尽量少使用事件编程是个明智的做法。
于是 事件委托 就出现了。
当页面上某个元素上的事件触发时,而在 DOM继承关系上,这个元素的所有子元素也能接收到这个事件,这时你可以使用一个在父元素上的事件处理器来处理,而不是使用一堆的各个子元素上的事件监听器来处理。究竟是什么意思?这样说吧,页面上有很多超链接,你不想直接使用这些链接,想通过一个函数来调用这个链接,HTML代码是这样的:
01.
Great Web resources
02.
"resources"
>
03.
"external nofollow"
class=
"external"
target=
"_blank"
href=
"
http://opera.com/wsc">OperaWeb Standards Curriculum
04.
"external nofollow"
class=
"external"
target=
"_blank"
href=
"
http://sitepoint.com">Sitepoint
05.
"external nofollow"
class=
"external"
target=
"_blank"
href=
"
http://alistapart.com">AList Apart
06.
"external nofollow"
class=
"external"
target=
"_blank"
href=
"
http://yuiblog.com">YUIBlog
07.
"external nofollow"
class=
"external"
target=
"_blank"
href=
"
http://blameitonthevoices.com">Blameit on the voices
08.
"external nofollow"
class=
"external"
target=
"_blank"
href=
"
http://oddlyspecific.com">Oddlyspecific
09.
常见的做法是通过循环这些链接,将每个链接上附加一个事件处理器:
01.
//典型的事件处理例子
02.
(
function
(){
03.
var
resources= document.getElementByIdx_x(
'resources'
);
04.
var
links= resources.getElementsByTagName_r(
'a'
);
05.
var
all= links.length;
06.
for
(
var
i=0;i
07.
//Attach a listener to each link
08.
links[i].addEventListener(
'click'
,handler,
false
);
09.
};
10.
function
handler(e){
11.
var
x= e.target;
//Get the link that was clicked
12.
alert(x);
13.
e.preventDefault();
14.
};
15.
})();
我们用一个事件处理器也能完成这项任务:
01.
(
function
(){
02.
var
resources= document.getElementByIdx_x(
'resources'
);
03.
resources.addEventListener(
'click'
,handler,
false
);
04.
function
handler(e){
05.
var
x= e.target;
//get the link tha
06.
if
(x.nodeName.toLowerCase()===
'a'
){
07.
alert(
'Eventdelegation:'
+x);
08.
e.preventDefault();
09.
}
10.
};
11.
})();
因为点击事件就发生在这些页面元素里,你要做的就是比较它们的 nodeName,找出应该回应这个事件的那个元素。
免责声明:上面说的这两个关于事件的例子,在所有浏览器里都能运行,除了IE6,在IE6上你需要使用一个事件模型,而不是简单的W3C的标准实现。这也就是我们推荐使用一些工具包的原因。
这种方法的好处并不是仅限于把多个事件处理器缩减为一个。你想想,举个例子,你需要动态的往这个链接表里追加更多的链接。使用事件委托后,你就不需要做其它修改了;否则的话,你需要重新循环这个链接表,重新给每个链接安装事件处理器。