on() 方法在被选元素及子元素上添加一个或多个事件处理程序。
自 jQuery 版本 1.7 起,on() 方法是 bind()、live() 和 delegate() 方法的新的替代品。该方法给 API 带来很多便利,我们推荐使用该方法,它简化了 jQuery 代码库。
注意:使用 on() 方法添加的事件处理程序适用于当前及未来的元素(比如由脚本创建的新元素)。
提示:如需移除事件处理程序,请使用 off() 方法。
提示:如需添加只运行一次的事件然后移除,请使用 one() 方法。
更加详细一点的说明:
.on()方法事件处理程序到当前选定的jQuery对象中的元素。在jQuery 1.7中,.on()方法 提供绑定事件处理的所有功能。为了帮助从旧的jQuery事件方法转换过来,查看 .bind(), .delegate(), 和 .live(). 要删除的.on()绑定的事件,请参阅.off()。要绑定一个事件,并且只运行一次,然后删除自己, 请参阅.one()
任何事件的名称,可以作为events 参数。jQuery将通过所有浏览器的标准JavaScript事件类型,当用户操作事件,如click,浏览器会调用handler参数的函数。此外,.trigger()方法可以触发标准的浏览器事件 和 自定义事件名绑定的处理程序。
事件名称可以添加指定的event namespaces(命名空间) 来简化删除或触发事件。例如,"click.myPlugin.simple"为 click 事件同时定义了两个命名空间 myPlugin 和 simple。通过上述方法绑定的 click 事件处理,可以用.off("click.myPlugin") 或 .off("click.simple")删除绑定到相应元素的Click事件处理程序,而不会干扰其他绑定在该元素上的“click(点击)” 事件。命名空间类似CSS类,因为它们是不分层次的;只需要有一个名字相匹配即可。以下划线开头的名字空间是供 jQuery 使用的。
在.on()方法的第二种用法中,events参数是一个JavaScript对象或者键值对。键等同于events参数,用空格分隔的事件名称字符串和可选命名空间。每个键的值是一个函数(或false 的值),相当于 handler 参数,但是该值并不是方法中的最后一个参数。在其它方面,这两种形式在下面描述的内容中其行为都是相同的。如下所述。
大多数浏览器事件冒泡, 或者 传播,都是由内到外的,从在文档最深处的元素( 事件目标 event target)开始, 一路传递到body和document元素。(注:事件冒泡简单的说就是,在冒泡路径上所有绑定了相同事件类型的元素上都会触发这些类型的事件。)在Internet Explorer 8和更低,一些事件,如change 和 submit本身不冒泡,但 jQuery 为了跨浏览器一致性, jQuery 在这些事件上模拟了冒泡行为。
如果省略selector或者是null,那么事件处理程序被称为直接事件 或者 直接绑定事件 。每次选中的元素触发事件时,就会执行处理程序,不管它直接绑定在元素上,还是从后代(内部)元素冒泡到该元素的
当提供selector参数时,事件处理程序是指为委派 事件(愚人码头注:通常也有很多人叫它代理事件)。事件不会在直接绑定的元素上触发,但当selector参数选择器匹配到后代(内部元素)的时候,事件处理函数才会被触发。jQuery 会从 event target 开始向上层元素(例如,由最内层元素到最外层元素)开始冒泡,并且在传播路径上所有绑定了相同事件的元素若满足匹配的选择器,那么这些元素上的事件也会被触发。
事件处理只能绑定在当前被选中的元素上;而且,在您的代码调用.on()的时候,他们必须已经存在。为了确保目前的元素可以被选择的(注:即,存在),最好将脚本放在元素的HTML标记的后面或者在 document 的 ready 事件中进行事件绑定。 如果新的HTML被注入页面时,新的HTML放置到页面后,事件会绑定到匹配选择器(selector参数)的元素。 或者,使用委派事件绑定事件处理程序,如下所述。
委托事件 有一个优势,他们能在后代元素添加到文档后,可以处理这些事件。在确保所选择的元素已经存在的情况下,进行事件绑定时,您可以使用委派的事件,以避免频繁的绑定事件及解除绑定事件。 例如,这个已经存在的元素可以是 Model-View-Controller(模型 - 视图 - 控制器)模式中 View(视图) 的一个容器元素,或document。如果想监视所有文档中的冒泡事件的话。在加载任何其它 HTML 之前,document 元素在 head 中就是有效的,所以您可以安全的在 head 中进行事件绑定,而不需要等待文档加载完。
除了可以给未创建的后代元素绑定事件外(即上面提到的优势),代理事件的另一个好处就是,当需要监视很多元素的时候,代理事件的开销更小。例如,在一个表格的 tbody 中含有 1,000 行,下面这个例子会为这 1,000 元素绑定事件:
$( "#dataTable tbody tr" ).on( "click", function() { console.log( $( this ).text() ); });一个委派事件的方法只在一个元素上绑定一个事件处理程序,下面的代码是绑定在tbody元素上,并且事件只会向上冒泡一层(从被点击的tr 到 tbody ):
$( "#dataTable tbody" ).on( "click", "tr", function() { console.log( $( this ).text() ); });注意: 委托事件不能用于SVG.
handler参数必须是一个函数(或false值,见下文), 除非你传递一个对象给events参数。 您可以提供一个匿名处理函数给.on()调用,就像上面例子中的用法,或者可以声明一个函数,然后再将该函数名作为参数:
function notify() { alert("clicked"); } $("button").on("click", notify);当浏览器触发一个事件或其他JavaScript调用的jQuery的.trigger()方法,jQuery传递一个Event对象给这个处理程序,它可以用来分析和改变事件的状态。这个对象是由浏览器提供一个数据的标注化子集;您需要浏览器自己的未经修改的原始 event 对象,您可以使用event.originalEvent得到。例如, event.type 包含事件的名称(例如, "resize" )和event.target表示触发事件的最深元素(最内层)。
默认情况下,大多数事件的冒泡从最初的 event target(目标元素) 开始的,直到document 元素。每个元素都沿着DOM层级这条路,jQuery会调用任何匹配的已被绑定的事件处理程序。一个处理程序可以调用的event.stopPropagation()防止事件向上冒泡文档树( 从而防止这些元素的处理程序运行)。任何绑定到当前元素上的其他处理程序都将运行,为了防止这种情况,可以调用event.stopImmediatePropagation()。(绑定在元素上的事件被调用的顺序和它们被绑定的顺序时一样的。 )
类似地,一个处理程序可以调用的event.preventDefault()取消浏览器默认操作行为;例如,一个链接上有一个 默认的click事件。并非所有的浏览器事件的默认操作,并非所有的默认操作可以被取消。有关详细信息,请参阅W3C Events Specification
调用event.stopPropagation() 和 event.preventDefault()会从一个事件处理程序会自动返回false。也可以直接将 false 当作 handler 的参数,作为 function(){ return false; } 的简写形式。因此,下面的写法 $("a.disabled").on("click", false); 将会阻止所有含有 "disabled" 样式的链接的默认行为,并阻止该事件上的冒泡行为。
当jQuery的调用处理程序时,this关键字指向的是当前正在执行事件的元素。对于直接事件而言,this 代表绑定事件的元素。对于代理事件而言,this 则代表了与 selector 相匹配的元素。(注意,如果事件是从后代元素冒泡上来的话,那么 this 就有可能不等于 event.target。)若要使用 jQuery 的相关方法,可以根据当前元素创建一个 jQuery 对象,即使用 $(this)。
如果data参数给.on()并且不是null 或者 undefined,那么每次触发事件时,event.data都传递给处理程序。data参数可以是任何类型,但如果是字符串类型时,那么selector参数必须提供,或明确地传递null,这样的 data 参数不会误认为是选择器。最好是使用一个对象(键值对) ,所以可以作为属性传递多个值。
jQuery的1.4 ,相同的事件处理程序可以多次绑定到一个元素。这对于使用 event.data 功能,或者在闭包中使用唯一的数据时是特别有用的。例如:
function greet( event ) { alert( "Hello " + event.data.name ); } $( "button" ).on( "click", { name: "Karl" }, greet ); $( "button" ).on( "click", { name: "Addy" }, greet );按一下按钮时,上面的代码会产生两个不同的警告(alert)。
除了可以向 .on() 方法传入 data 参数外,还可以向 .trigger() 或 .triggerHandler() 中传入该参数。 这种方式提供数据(Data)被传递给事件处理程序的Event 对象内,作为进一步的参数。 如果传递给.trigger() 和 .triggerHandler()的第二个参数是一个数组, 数组中的每个元素将作为事件处理程序的单独参数。(注:参见.trigger())
在大多数情况下,一个事件如click很少发生,性能表现并不显注。但是,高频率事件比如mousemove 或者 scroll可以每秒触发几十个次,在这种情况下明智地使用事件变得更加重要。可以按如下的办法提高事件的性能:减少事件处理函数中的工作量;对于在事件处理函数中要用到的信息做好缓存而不是再重新计算一次;或使用setTimeout限制的页面更新的实际次数。
许多委派的事件处理程序绑定到 document 树的顶层附近,可以降低性能。每次发生事件时,jQuery 需要比较从 event target(目标元素) 开始到文档顶部的路径中每一个元素上所有该类型的事件。为了获得更好的性能,在绑定代理事件时,绑定的元素最好尽可能的靠近目标元素。避免在大型文档中,过多的在 document 或 document.body 上添加代理事件。
jQuery可以非常迅速处理tag#id.class形式的简单选择器,当它们是用来过滤委派事件。所以"#myForm", "a.external", 和 "button" 都是快速选择器。若代理事件的选择器使用了过于复杂的形式,特别是使用了分层选择器的情况,虽然说这样做会大大的降低性能,但是对于大多数应用而言,它的速度依然是足够快的。通过为寻找更合适的元素绑定事件的方法,就可以很简单的避免使用分层选择器的情况。例如,使用$("#commentForm").on("click", ".addNew", addComment)而不是$("body").on("click", "#commentForm .addNew", addComment)。
有一些事件的速记方法比如.click()可用于附加或触发事件处理程序。对于速记方法的完整列表, 参见events category
虽然不建议,伪类事件名称"hover"可以作为"mouseenter mouseleave"的缩写使用。不要与 接受两个函数的.hover()方法混淆,这里只用一个处理函数绑定到伪类事件名称"hover";处理程序应该检查的event.type 以确定是否是mouseenter或 mouseleave事件。
jQuery的事件系统需要一个DOM元素可以通过元素的属性附加数据,使事件就可以被跟踪和传递。object, embed, 和applet元素不能绑定数据,因此不能有jQuery的事件绑定。
W3C指定明确指定focus 和 blur事件没有冒泡,但是jQuery定义的跨浏览器的focusin 和 focusout事件,并且可以冒泡。当focus 和 blur绑定委派的事件处理程序时,jQuery分析名称,并提供将他们分别交付给focusin 和 focusout。为了保持一致性和清晰度,使用冒泡事件类型的名称。
在所有的浏览器,load ,scroll, 和 error 事件(例如, 在一个 <img> 元素上)不会冒泡。在Internet Explorer 8和更低,paste 和 reset事件不会冒泡,这样的事件是不支持委派使用,但若事件处理函数是直接绑定在产生事件的元素上的话,是可以使用这些事件的。
window对象上的error 事件使用非标准的参数和返回值约定,所以jQuery 不支持该事件。作为替代,直接用window.onerror属性分配一个处理函数。
当事件被首次触发时,处理函数列表才会被设置到元素上。当前元素上添加或删除事件处理函数不会立即生效,直到下一次的事件被处理。 为了避免任何后续事件处理函数在一个元素的事件处理函数中执行,调用event.stopImmediatePropagation() 这种行为违反了W3C的事件规范。 为了更好地了解这种情况下,考虑下面的代码:
var $test = $( "#test" ); function handler1() { console.log( "handler1" ); $test.off( "click", handler2 ); } function handler2() { console.log( "handler2" ); } $test.on( "click", handler1 ); $test.on( "click", handler2 );在上面的代码,handler2第一次无路如何都会被执行,即使使用.off()删除。 然而,该处理函数在下一次click事件被触发时将不执行。
以点击事件("click")为例,以下是jQuery中事件函数的常规用法(某些函数也存在其它形式的用法,此处暂不列出):
1 // 这里的选择器selector用于指定可以触发事件的元素 2 // 这里的选择器ancestor应是selector的祖辈元素,selector触发的事件可以被其祖辈元素在事件流中捕获,从而以"代理"的形式触发事件。 3 4 // jQuery 1.0+ (1.4.3+支持参数data) 5 $("selector").click( [ data ,] handler ); 6 7 // jQuery 1.0+ (1.4.3+支持参数data) 8 $("selector").bind( "click" [, data ], handler ); 9 10 // jQuery 1.3+ (1.4+支持参数data) 11 $("selector").live( "click" [, data ], handler ); 12 13 // jQuery 1.4.2+ 14 $("ancestor").delegate( "selector", "click" [, data ], handler ); 15 16 // jQuery 1.7+ 17 $("ancestor").on( "click", "selector" [, data ], handler );请参考下面这段初始HTML代码:
1 <div id="n1"> 2 <p id="n2"><span>CodePlayer</span></p> 3 <p id="n3"><span>专注于编程开发技术分享</span></p> 4 <em id="n4">http://www.365mini.com</em> 5 </div> 6 <p id="n5">Google</p>我们为<div>中的所有<p>元素绑定点击事件:
1 // 为div中的所有p元素绑定click事件处理程序 2 // 只有n2、n3可以触发该事件 3 $("div").on("click", "p", function(){ 4 // 这里的this指向触发点击事件的p元素(Element) 5 alert( $(this).text() ); 6 });如果要绑定所有的<p>元素,你可以编写如下jQuery代码:
1 //为所有p元素绑定click事件处理程序(注意:这里省略了selector参数) 2 //n2、n3、n5均可触发该事件 3 $("p").on("click", function(event){ 4 // 这里的this指向触发点击事件的p元素(Element) 5 alert( $(this).text() ); 6 });此外,我们还可以同时绑定多个事件,并为事件处理函数传递一些附加的数据,我们可以通过jQuery为事件处理函数传入的参数event(Event事件对象)来进行处理:
1 var data = { id: 5, name: "张三" }; 2 3 // 为n5绑定mouseenter mouseleave两个事件,并为其传入附加数据data 4 // 附加数据可以是任意类型 5 $("body").on("mouseenter mouseleave", "#n5", data, function(event){ 6 var $me = $(this); 7 var options = event.data; // 这就是传入的附加数据 8 if( event.type == "mouseenter"){ 9 $me.html( "你好," + options.name + "!"); 10 }else if(event.type == "mouseleave" ){ 11 $me.html( "再见!"); 12 } 13 });此外,即使符合条件的元素是on()函数执行后新添加,绑定事件对其依然有效。同样以初始HTML代码为例,我们可以编写如下jQuery代码:
1 // 为div中的所有p元素绑定click事件处理程序 2 // 只有n2、n3可以触发该事件 3 $("div").on("click", "p", function(event){ 4 alert( $(this).text() ); 5 }); 6 7 // 后添加的n6也可以触发上述click事件,因为它也是div中的p元素 8 $("#n1").append('<p id="n6">上述绑定的click事件对此元素也生效!</p>');参数events还支持为事件类型附加额外的命名空间。当为同一元素绑定多个相同类型的事件处理函数时。使用命名空间,可以在触发事件、移除事件时限定触发或移除的范围。
1 function clickHandler(event){ 2 alert( "触发时的命名空间:[" + event.namespace + "]"); 3 } 4 5 var $p = $("p"); 6 7 // A:为所有p元素绑定click事件,定义在foo和bar两个命名空间下 8 $p.on( "click.foo.bar", clickHandler ); 9 10 // B:为所有p元素绑定click事件,定义在test命名空间下 11 $p.on( "click.test", clickHandler ); 12 13 var $n2 = $("#n2"); 14 15 // 触发所有click事件 16 $n2.trigger("click"); // 触发A和B (event.namespace = "") 17 18 // 触发定义在foo命名空间下的click事件 19 $n2.trigger("click.foo"); // 触发A (event.namespace = "foo") 20 // 触发定义在bar命名空间下的click事件 21 $n2.trigger("click.bar"); // 触发A (event.namespace = "bar") 22 // 触发同时定义在foo和bar两个命名空间下的click事件 23 $n2.trigger("click.foo.bar"); // 触发A (event.namespace = "bar.foo") 24 25 // 触发定义在test命名空间下的click事件 26 $n2.trigger("click.test"); // 触发B (event.namespace = "test") 27 28 // 移除所有p元素定义在foo命名空间下的click事件处理函数 29 $p.off( "click.foo" ); // 移除A 30 31 on()函数的参数eventsMap是一个对象,可以"属性-值"的方式指定多个"事件类型-处理函数"。对应的示例代码如下: 32 33 var data = { id: 5, name: "张三" }; 34 35 var events = { 36 "mouseenter": function(event){ 37 $(this).html( "你好," + event.data.name + "!"); 38 }, 39 40 "mouseleave": function(event){ 41 $(this).html( "再见!"); 42 } 43 }; 44 45 //为n5绑定mouseenter mouseleave两个事件,并为其传入附加数据data 46 $("body").on(events, "#n5", data);