Page 33 - JavaScript修炼之道
P. 33
20 第二部分 DOM、事件及定时器
任务 9 利用事件委托
请用心理解并牢记这句话:优先使用事件委托。
你应该知道,绝大多数的事件可以冒泡,比如说鼠标或键盘事件。当这些事件在DOM某处
发生时,它们会沿着祖先元素这条线,从内向外依次触发各个元素,直到文档的根元素(如果这
些元素中的任何一个都没有监听器来阻止冒泡继续的话)。
假设我们有大量的元素,而且这些元素需要共享同一个行为。如果需要在这些元素上监听事
件,我们最好在DOM的高层次,也就是离这些元素最近的公共祖先上或在document上监听事件。
这样可以节省大量的内存和CPU时间。
在DOM的高层监听事件对加载Ajax内容的行为也有好处。由于你在加载内容的“外面”进
行监听,因此新添加进来的元素会自动获得现有的行为,而不需要在加载后设置额外的监听器。
不过,有时我们的触发事件不会冒泡,这时我们就需要对事件委托进行一些hack,或是完全
抛弃事件委托。毫无疑问,submit、focus和blur这些事件不会冒泡——这使得对共享表单及域
的处理变成了一场噩梦。尽管存在一些代码来模拟这些事件的冒泡,但这些事件的不可冒泡性仍
令人感到不爽。
需要指出的是,直到1.4版本,jQuery的live()方法才开始在本质上灵活地支持事件委托,
而且不会带来性能问题。也是从那个版本开始,jQuery增加了操作非冒泡事件的能力。此外,Dojo
的behavior()看起来像是使用了事件代理,但其实并非如此。实际上它只是一个不错的语法糖。
注意示例代码第2行上的findElement()调用。当前,我们的链接只包含一段简单的文本,
所以在链接内部单击也就意味着单击链接本身。不过,假设你在这个链接上面加了一个图标(比
如说一个加/减图标),那么单击可能发生在图标上,但它仍然是单击链接事件。因此,在Prototype
中指派一个基于委托的事件代理处理器时,请使用事件的findElement()方法,而非不太智能的
element()方法。