42-讨论
8.10.3 讨论
1.为什么事件处理程序不见了
和CSS相反,JavaScript不是一种声明性的语言。不用描述各种行为,它们都会“像魔术一样自动”应用。
JavaScript和许多其他语言一样是命令式语言。开发人员指定需要执行的一系列操作,这些操作在代码执行到该行的时候应用。
当添加如下这段代码时:
function handler(){
alert('got clicked');
}
jQuery('.clickable').bind('click', handler);
下面就是所要做的:
1.查找所有CSS类为“clickable”的元素,将其保存在集合里。
2.将“处理程序”函数绑定到集合中每个元素的单击事件。
如果JavaScript/jQuery进行声明性的解释,上述代码的意思如下:
每当单击CSS类为 clickable 的元素,就运行 handler 函数。
但是,因为JavaScript/jQuery的解释是命令式的,只有在运行时匹配选择器的元素才会绑定。如果用 clickable 类添加新元素或者从元素上删除该类,不会添加或者删除这些元素的行为。
2.事件委托简介
事件委托就是在开始时绑定一次,然后被动地监听事件的触发。它依赖浏览器中的许多事件都会冒泡这一事实。
举一个例子,在单击一个 <div> 之后,它的双亲节点也会接收单击事件,然后传递给双亲的双亲,依此类推直到它到达 document 元素。
3.每种方法的优点和缺点
重新绑定 。重新绑定很简单:你只是重新添加事件处理程序。它会导致新的问题,例如,为已经绑定事件处理程序的元素添加事件处理程序。有些人添加CSS类来解决这一问题(用某个类标记已经绑定的元素)。
所有这些处理在每次元素更新的时候都需要CPU周期,而且需要创建越来越多的事件处理程序。
同时解决这两个问题的方法之一是使用命名函数作为事件处理程序。如果你始终使用同一个函数,就已经解决了重复的问题,开销也较小。
但是,重新绑定仍然可能随着时间的推移导致越来越高的内存消耗。
事件委托 。事件委托只要求在开始的时候绑定,完全没有必要处理重新绑定。这对于开发人员来说相当轻松,而且使代码更加简短,也更加清晰。前面提到的RAM问题不适用于事件委托。页面的内容可能变化,但是活动的事件处理程序总是相同。
但是,事件委托也有需要小心的地方。为了使其正常工作,处理代码( live() 、插件或者你自己的代码)必须取得发生事件的元素( event.target )并遍历它的祖先元素,查看哪一个元素有可以触发的事件处理程序,此外还有一些其他的处理。这意味着,虽然事件委托需要的绑定较少,但是每次触发事件时需要更多的处理。
而且,事件委托无法用于不进行冒泡的事件,例如, focus 和 blur 。对于这些事件来说,有一个跨浏览器的替代方法,就是在某些浏览器中使用 focusin 和 focusout 。
4.结论
事件委托似乎是更好的方法,但是需要额外的处理。对此,我建议只在真正需要的时候使用实时绑定。有两种常见的情况需要事件委托:
动态元素
有一系列动态变化的DOM元素。
大的列表
当用实时绑定只需要一次绑定,而不是常规方法中的100次时,事件委托运行速度更快。这种方法在开始时更快,占用的内存也较少。
如果没有理由使用 live() ,那么就使用 bind() 。如果以后需要改为实时方式,切换也就是几秒钟的事情。
[1]http://en.wikipedia.org/wiki/Event-driven_programming。
[2]http://docs.jquery.com/Events/jQuery.Event#event.data。
[3]http://docs.jquery.com/Events/jQuery.Event。
[4]http://docs.jquery.com/Events/live。
[5]http://plugins.jquery.com/project/LiveQuery。
[6]http://plugins.jquery.com/project/ElementReady。
[7]http://docs.jquery.com/Events/jQuery.Event#event.stopPropagation.28.29。
[8]http://docs.jquery.com/Events/jQuery.Event#event.stopImmediatePropagation.28.29。
[9]http://www.w3.org/TR/DOM-Level-3-Events/。
[10]http://docs.jquery.com/Events/jQuery.Event#event.isImmediatePropagationStopped.28.29。
[11]http://docs.jquery.com/Events/jQuery.Event#event.target。
[12]http://docs.jquery.com/Traversing/closest。
[13]http://www.quirksmode.org/js/events_order.html。
[14]http://en.wikipedia.org/wiki/DOM_events#Common.2FW3C_events。