返回值:jQueryon(events, [selector], [data], handler(eventObject))
为选中元素上的一个或多个事件绑定事件处理函数。
-
1.7 新增on(events, [selector], [data], handler(eventObject))
events (String) 一个或多个由空格分隔的事件类型及可选的名字空间,例如:"click" 或 "keydown.myPlugin"。selector (String) 可选参数,一个选择器字符串,用于过滤出被选中的元素中能触发事件的后代元素。如果选择器是null
或者忽略了该选择器,那么被选中的元素总是能触发事件。data (Anything) 可选参数,当事件触发时,将要传入事件处理函数中的event.data
的数据。handler(eventObject) (Function) 当事件被触发时,执行的函数。若该函数只是要执行return false
的话,那么该参数位置可以直接简写成false
。 -
1.7 新增on(events-map, [selector], [data])
events-map (Map) 一个映射,键是由一个或多个由空格分隔的事件类型及可选的名字空间,值是这些事件类型所对应的事件处理函数。selector (String) 可选参数,一个选择器字符串,用于过滤出被选中的元素中能触发事件的后代元素。如果选择器是null
或者忽略了该选择器,那么被选中的元素总是能触发事件。data (Anything) 可选参数,当事件触发时,将要传入事件处理函数中的event.data
的数据。
.on()
方法会在 jQuery 对象中将当前被选中的元素的上绑定事件。从 jQuery 1.7 开始,.on()
方法提供了绑定事件处理的所有功能。为了帮助您更好的将旧的 jQuery 事件方法转换成新的方法,您可以参阅 .bind()
, .delegate()
, 和 .live()
方法。若要移除通过 .on()
绑定的事件,请使用 .off()
。若要绑定仅执行一次之后就被删除的事件,请使用 .one()
。
事件名和名字空间
任何事件名都可以作为 events
参数。当浏览器根据用户的动作(例如,click
)产生事件时,jQuery 将通过浏览器的标准 JavaScript 事件类型,调用 handler
函数。此外,.trigger()
方法既可以根据标准的浏览器事件名触发事件,也可以根据自定义的事件名触发事件。
还可以为事件名添加指定一个事件名字空间,这样可以简化事件移除或触发。例如,"click.myPlugin.simple"
为 click 事件同时定义了两个名字空间 myPlugin 和 simple。通过上述方法绑定的 click 事件处理,可以使用 .off("click.myPlugin")
或 .off("click.simple")
来移除,而且还不会影响绑定在该元素上的其它 click 事件。名字空间与 CSS 样式类似,它们都不分层次,只需要有一个名字相匹配即可。以下划线开头的名字空间是供 jQuery 使用的。
在 .on(events-map, [selector], [data])
这种用法中,events-map
参数是一个 JavaScript 对象,或者是 "map"。该参数的键的形式与 events
参数相同,也就是由空格分隔的事件类型及可选的名字空间。该参数的值是与键相对应的处理函数(或者是 false
),相当于 .on(events, [selector], [data], handler(eventObject))
中的 handler
参数,但是该值并不是方法中的最后一个参数。在其它方面,这两种形式在下面描述的内容中其行为都是相同的。
直接事件和代理事件
大多数浏览器事件的冒泡或传播都是由内而外的(从 event target 开始)直到 body 及 document
元素,并且在传播路径上所有绑定了相同事件的元素上的这些事件都会被触发。在 Internet Explorer 8 及其早先的版本中,有一些事件,例如,change
和 submit
是不会本能的进行冒泡的,但 jQuery 为了跨浏览器的一致性,在这些事件上模拟了冒泡行为。
如果忽略了 selector
参数,或者该参数为 null,那么这种事件处理就被称之为直接事件或直接绑定事件。只要被选中元素上有事件发生时,那么事件处理函数每次都会被调用,无论它是元素上的直接事件还是从后代元素上冒泡上来的事件。
当提供了 selector
参数时,事件处理就被称之为代理事件。当事件直接发生在绑定的元素上时,事件处理函数是不会被触发的,只有其后代元素与提供的选择器相匹配时,事件处理函数才会被触发。jQuery 会从 event target 开始向上层元素(例如,由最内层元素到最外层元素)开始冒泡,并且在传播路径上所有绑定了相同事件的元素若满足匹配的选择器,那么这些元素上的事件也会被触发。
事件处理只能绑定在当前被选中的元素上。并且,当调用 .on()
的时候,这些被选中的元素必须是在页面中存在的。为了保证元素是存在的,并且能够被选中,最好是在 document 的 ready 事件中进行事件绑定。如果有新的 HTML 被注入到页面中时,那么当新的 HTML 在页面上生成完之后,再进行元素选择,并绑定事件。也可以像下面提到的那样,使用代理事件进行事件绑定。
代理事件有一个优势,那就是它可以处理在经过事件绑定之后又添加的后代元素上的事件。在确保所选择的元素已经存在的情况下,进行事件绑定时,您可以使用代理事件从而避免频繁的绑定事件及解除绑定事件。例如,这个已经存在的元素可以是 Model-View-Controller 模式中 View 的一个容器元素,也可以是 document
,若您想监视所有文档中的冒泡事件的话。在加载任何其它 HTML 之前,document
元素在 head
中就是有效的,所以您可以安全的在 head
中进行事件绑定,而不需要等待文档加载完。
除了可以给未创建的后代元素绑定事件外(即上面提到的优势),代理事件的另一个好处就是,当需要监视很多元素的时候,代理事件的开销更小。例如,在一个表格的 tbody
中含有 1,000 行,下面这个例子会为这 1,000 元素绑定事件:
$("#dataTable tbody tr").on("click", function(event){ alert($(this).text()); });
然而,使用代理事件时,只需要为一个元素 tbody 绑定事件,并且事件只会向上冒泡一层(从被点击的 tr
到 tbody
):
$("#dataTable tbody").on("click", "tr", function(event){ alert($(this).text()); });
事件处理函数和它的运行环境
handler
参数是一个函数(或者是一个 false
值,请看下文),并且该参数是必须的参数,除非采用的是 events-map
形式。您可以在调用 .on()
时,提供一个匿名函数,就像上面例子中的用法,或者可以声明一个函数,然后再将该函数名作为参数:
function notify() { alert("clicked"); } $("button").on("click", notify);
当浏览器触发一个事件或使用其它 JavaScript 调用了 jQuery 的 .trigger()
方法时,jQuery 会为处理函数传入一个 event 对象
,可以使用它来分析或改变事件的状态。该对象包含了一个浏览器提供的数据的标准化子集(normalized subset),而您需要浏览器自己的未经修改的原始 event 对象,您可以使用 event.originalEvent
来获得。例如,event.type
包含事件名(例如,"resize") 和 event.target
代表最内层的发生事件的元素。
默认情况下,大多数事件冒泡是从最初的 event target 开始的,直至 document
元素。并且在传播路径上所有绑定了相同事件的元素上的这些事件都会被触发。可以通过调用 event.stopPropagation()
来阻止事件在文档树中向上冒泡(这样就可以阻止这些元素上的事件被触发)。任何绑定在当前元素上的其它事件将会执行。为了防止这种事件发生,可以调用 event.stopImmediatePropagation()
。(绑定在元素上的事件被调用的顺序和它们被绑定的顺序是一致的。)
类似的,可以在事件处理函数中调用 event.preventDefault()
来取消浏览器在该事件上的默认动作。例如,跟随在链接之后的 click
事件的默认动作。不是所有的浏览器事件都有默认动作,而且也不是所有的默认动作都可以被取消。了解更多内容,请参阅 W3C 事件规范。
若在事件处理中返回 false
的话,会自动调用 event.stopPropagation()
和 event.preventDefault()
。也可以直接将 false
当作 handler
的参数,作为 function(){ return false; }
的简写形式。因此,下面的写法 $("a.disabled").on("click", false);
将会阻止所有含有 "disabled" 样式的链接的默认行为,并阻止该事件上的冒泡行为。
当 jQuery 调用事件处理函数时,关键字 this
指向的是当前正在执行事件的元素。对于直接事件而言,this
代表绑定事件的元素。对于代理事件而言,this
则代表了与 selector
相匹配的元素。(注意,如果事件是从后代元素冒泡上来的话,那么 this
就有可能不等于 event.target
。)若要使用 jQuery 的相关方法,可以根据当前元素创建一个 jQuery 对象,即使用 $(this)
。
向事件处理函数传入数据
如果向 .on()
中传入了 data
参数,并且该参数不等于 null
或 undefined
的话,那么当事件被触发时,就可以使用 event.data
属性来获得传入的参数。data
参数可以是任何类型,但若是字符串类型的话,则必须同时提供 selector
参数,若您不想提供 selector
参数的话,请显式的使用 null
。这么做的目的是为了不会将提供的 data 参数误当作选择器。最好使用一个对象(map)作为传入的参数,这样就可以同时传入很多的值。
从 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);
当点击按钮时,上述代码会产生两个不同的提示框。
除了可以向 .on()
方法传入 data
参数外,还可以向 .trigger() 和 .triggerHandler() 中传入该参数。
事件性能
在大多数情况下,因为事件(例如 click
)发生的频率并不是很高,所以我们最关心并不是事件的性能。然而,对于高频事件,例如 mousemove
或 scroll
,通常会在一秒钟发生很多次。因此,在这种情况下,如果明智的使用事件就变得更加的重要。可以按如下的办法提高事件的性能:减少事件处理函数中的工作量;对于在事件处理函数中要用到的信息做好缓存而不是再重新计算一次;减少使用 setTimeout
更新页面的次数。
若在 document 树的顶层附近绑定很多代理事件的话,可能会使性能变得更差。每次发生事件时,jQuery 需要比较从 event target 开始到文档顶部的路径中每一个元素上所有该类型的事件。为了获得更好的性能,在绑定代理事件时,绑定的元素最好尽可能的靠近目标元素。避免在大型文档中,过多的在
document
或 document.body
上添加代理事件。
当使用 tag#id.class
表单中的选择器来过滤代理事件时,jQuery 可以简单而快速的处理这种选择器。因此,"#myForm"
, "a.external"
,和 "button"
都是非常快速的选择器。若代理事件的选择器使用了过于复杂的形式,特别是使用了分层选择器的情况,虽然说这样做会大大的降低性能,但是对于大多数应用而言,它的速度依然是足够快的。通过为寻找更合适的元素绑定事件的方法,就可以很简单的避免使用分层选择器的情况。例如,使用
$("#commentForm").on("click", ".addNew", addComment)
来代替 $("body").on("click", "#commentForm .addNew", addComment)
。
补充说明
对于很多事件都有简写形式(例如 .click()
)可以用于绑定或触发事件处理函数。完整的事件简写列表,请参阅 事件类别。
从 jQuery 1.8 开始,不建议使用的方法: "hover"
是字符串 "mouseenter mouseleave"
的简写形式。它为上述两个事件,绑定一个单一事件处理函数,而且,处理函数必须检查 event.type
来判断到底是 mouseenter
还是 mouseleave
。不要将 "hover" 伪事件名和 .hover()
方法混为一谈, .hover()
可以接受一个或两个函数。
jQuery 的事件系统要求,一个 DOM 元素可以通过元素的属性附加数据,这样,事件就可以被跟踪和传递。object
, embed
, 和 applet
元素是不能附加数据的,因此,无法为这些元素绑定 jQuery 事件。
根据 W3C 的规定,focus
和 blur
事件是不能进行冒泡的,但是 jQuery 定义了跨浏览器的 focusin
和 focusout
事件,从而实现了事件的冒泡。当 focus
和 blur
用于绑定代理事件的时候,jQuery 会将它们映射成对应的 focusin
或 focusout
。为了保证使用上的一致和清晰,请使用支持冒泡事件的事件名。
jQuery 同样明确的禁止了鼠标右键和中键的冒泡行为。因为它们并不在元素被点击的时候触发。若需要检测鼠标中键的动作,请 .on()
来代替 mousedown
和 mouseup
。
在所有的浏览器中,load
, scroll
,和 error
事件(例如,在 <img>
元素上)是不会进行冒泡的。在 Internet Explorer 8 及早先版本中,paste
和 reset
事件也不会发生冒泡现象。因此,无法在代理事件中使用这些事件。但若事件处理函数是直接绑定在产生事件的元素上的话,是可以使用这些事件的。
由于 window
对象上的 error
事件使用了非标准参数和返回值约定,因此 jQuery 不支持该事件。可以采用为 window.onerror
属性直接添加事件处理函数的方法来代替。
示例:
当点击段落时,显示该段落中的文本:
jQuery 代码:
$("p").on("click", function(){
alert( $(this).text() );
});
示例:
向事件处理函数中传入数据,并且在事件处理函数中通过名字来获取传入的数据:
jQuery 代码:
function myHandler(event) {
alert(event.data.foo);
}
$("p").on("click", {foo: "bar"}, myHandler)
示例:
取消表单的提交动作,并且通过返回 false 的方法来防止事件冒泡:
jQuery 代码:
$("form").on("submit", false)
示例:
通过使用 .preventDefault(),仅取消默认的动作。
jQuery 代码:
$("form").on("submit", function(event) {
event.preventDefault();
});
示例:
通过使用 .stopPropagation(),防止提交事件的冒泡行为,但是并不禁止提交行为。
jQuery 代码:
$("form").on("submit", function(event) {
event.stopPropagation();
});
示例:
添加并触发自定义事件(非浏览器事件)。
<!DOCTYPE html>
<html>
<head>
<style>
p { color:red; }
span { color:blue; }
</style>
<script src="jquery.min.js"></script>
</head>
<body>
<p>Has an attached custom event.</p>
<button>Trigger custom event</button>
<span style="display:none;"></span>
<script>
$("p").on("myCustomEvent", function(e, myName, myValue){
$(this).text(myName + ", hi there!");
$("span").stop().css("opacity", 1)
.text("myName = " + myName)
.fadeIn(30).fadeOut(1000);
});
$("button").click(function () {
$("p").trigger("myCustomEvent", [ "John" ]);
});
</script>
</body>
</html>
演示:
示例:
使用 map 同时添加多个事件处理函数。
<!DOCTYPE html>
<html>
<head>
<style>
.test { color: #000; padding: .5em; border: 1px solid #444; }
.active { color: #900;}
.inside { background-color: aqua; }
</style>
<script src="jquery.min.js"></script>
</head>
<body>
<div class="test">test div</div>
<script>
$("div.test").on({
click: function(){
$(this).toggleClass("active");
},
mouseenter: function(){
$(this).addClass("inside");
},
mouseleave: function(){
$(this).removeClass("inside");
}
});
</script>
</body>
</html>
演示:
示例:
点击任何一个段落时,就在它后面追加一个段落。注意,.on() 会为任何段落添加事件,包括新生成的段落,因为当事件冒泡到已经存在的 body 元素上时,就会触发绑定的事件。
<!DOCTYPE html>
<html>
<head>
<style>
p { background:yellow; font-weight:bold; cursor:pointer;
padding:5px; }
p.over { background: #ccc; }
span { color:red; }
</style>
<script src="jquery.min.js"></script>
</head>
<body>
<p>Click me!</p>
<span></span>
<script>
var count = 0;
$("body").on("click", "p", function(){
$(this).after("<p>Another paragraph! "+(++count)+"</p>");
});
</script>
</body>
</html>
演示:
示例:
当点击段落时,显示该段落中的文本:
jQuery 代码:
$("body").on("click", "p", function(){
alert( $(this).text() );
});
示例:
使用 preventDefault 方法,取消链接的默认动作。
jQuery 代码:
$("body").on("click", "a", function(event){
event.preventDefault();
});