在讲on()方法之前,我们先讲讲在on()方法出现前的那些事件绑定方法:
.live()
jQuery 1.3新增的live()方法,使用方法例如以下:
$("#info_table td").live("click",function(){/*显示很多其它信息*/});
这里的.live()方法会把click事件绑定到$(document)对象,并且仅仅须要给$(document)绑定一次,然后就行处理兴许动态载入的单元格的单击事件。
在接收到不论什么事件时。$(document)对象都会检查事件类型和事件目标,假设是click事件且事件目标是td。那么就运行托付给它的处理程序。
到眼下为止,一切似乎非常完美。可惜,事实并不是如此。由于.live()方法并不完美。它有例如以下几个主要缺点:
- $()函数会找到当前页面中的全部td元素并创建jQuery对象。但在确认事件目标时却不用这个td元素集合,而是使用选择符表达式与event.target或其祖先元素进行比較,因而生成这个jQuery对象会造成不必要的开销。
- 默认把事件绑定到$(document)元素,假设DOM嵌套结构非常深,事件冒泡通过大量祖先元素会导致性能损失;
- 仅仅能放在直接选择的元素后面,不能在连缀的DOM遍历方法后面使用,即$("#infotable td").live...能够,但$("#infotable").find("td").live...不行。
- 收集td元素并创建jQuery对象,但实际操作的却是$(document)对象,令人费解。
解决之道
为了避免生成不必要的jQuery对象。能够使用一种叫做“早托付”的hack。即在$(document).ready()方法外部调用.live():
(function($){
$("#info_table td").live("click",function(){/*显示很多其它信息*/});
})(jQuery);
在此,(function($){...})(jQuery)是一个“马上运行的匿名函数”,构成了一个闭包,能够防止命名冲突。在匿名函数内部,$參数引用jQuery对象。这个匿名函数不会等到DOM就绪就会运行。注意,使用这个hack时,脚本必须是在页面的head元素中链接和(或)运行的。之所以选择这个时机,由于这时候刚好document元素可用,而整个DOM还远未生成;假设把脚本放在结束的body标签前面,就没有意义了,由于那时候DOM已经全然可用了。
为了避免事件冒泡造成的性能损失,jQuery从1.4開始支持在使用.live()方法时配合使用一个上下文參数:
$("td",$("#info_table")[0]).live("click",function(){/*显示很多其它信息*/});
这样。“受托方”就从默认的$(document)变成了$("#infotable")[0]。节省了冒泡的旅程。
只是,与.live()共同使用的上下文參数必须是一个单独的DOM元素,所以这里指定上下文对象时使用的是$("#infotable")[0],即使用数组的索引操作符来取得的一个DOM元素。
.delegate()
如前所述,为了突破单一.bind()方法的局限性。实现事件托付,jQuery 1.3引入了.live()方法。后来。为解决“事件传播链”过长的问题,jQuery 1.4又支持为.live()方法指定上下文对象。而为了解决无谓生成元素集合的问题。jQuery 1.4.2干脆直接引入了一个新方法.delegate()。
使用.delegate(),前面的样例能够这样写:
$("#info_table").delegate("td","click",function(){/*显示很多其它信息*/});
使用.delegate()有例如以下长处(或者说攻克了.live()方法的例如以下问题):
- 直接将目标元素选择符("td")、事件("click")及处理程序与“受拖方”$("#info_table")绑定,不额外收集元素、事件传播路径缩短、语义明白;
- 支持在连缀的DOM遍历方法后面调用。即支持$("table").find("#info").delegate...,支持精确控制。
可见,.delegate()方法是一个相对完美的解决方式。但在DOM结构简单的情况下。也能够使用.live()。
提示:使用事件托付时,假设注冊到目标元素上的其它事件处理程序使用.stopPropagation()阻止了事件传播,那么事件托付就会失效。
在下列情况下。应该使用.live()或.delegate()。而不能使用.bind():
- 为DOM中的非常多元素绑定同样事件;
- 为DOM中尚不存在的元素绑定事件;
接下来就是今天的主角-------------------------------on()
.on()
依据jQuery 1.7 Beta 1 的发版说明,jQuery 1.7为了解决.bind()、.live()和.delegate()并存造成的不一致性问题,将会添加一对新的事件方法:.on()和.off(),下面为on()的实现方式:
.on( events [, selector ] [, data ], handler(eventObject) )
一个简单的事件绑定如 $('button').on('click',function(){}); 与bind()无二样。
在须要为较多的元素绑定事件的时候。优先考虑事件托付,能够带来性能上的优点。比方:
结果:
如上图,将click事件绑定在document对象上,页面上不论什么元素发生的click事件都冒泡到document对象上得到处理。
注意到.on()的描写叙述中第二个可选參数:selector。例如以下图,加入了第二个參数,选择符button:
结果:
当事件冒泡到document对象时,检測事件的target,假设与传入的选择符(这里是button)匹配,就触发事件。否则不触发。
注意.on()也能够接收一个对象參数,该对象的属性是事件类型,属性值为事件处理函数。
最后有一点,原先的live()方法,处理函数是默认绑定在document对象上不能变的,假设DOM嵌套结构非常深,事件冒泡通过大量祖先元素会导致较大的性能损失。而使用.on()方法,事件仅仅会绑定到$()函数的选择符表达式匹配的元素上(上面我的样例中。为了简单绑定到了document)。因此能够精确地定位到页面中的一部分,而事件冒泡的开销也能够降低。
delegate()与on()同理,毕竟是用on()实现的:
.on()和.off():实现方式
$(elems).on(events, selector, data, fn);
$(elems).off(events, selector, fn);
假设指定selector。则为事件托付;否则,就是常规绑定。