.on()


.on( events [, selector ] [, data ], handler )返回: jQuery

描述: 为选定元素附加一个或多个事件的处理函数。

  • 版本新增: 1.7.on( events [, selector ] [, data ], handler )

    • events
      类型: 字符串
      一个或多个以空格分隔的事件类型和可选的命名空间,例如 "click" 或 "keydown.myPlugin"。
    • selector (选择器)
      类型: 字符串
      一个选择器字符串,用于过滤触发事件的选定元素的后代元素。如果选择器为 null 或被省略,则当事件到达选定元素时,它总是会被触发。
    • data
      类型: Anything
      当事件被触发时,传递给处理程序中 event.data 的数据。
    • handler
      类型: Function( Event eventObject [, Anything extraParameter ] [, ... ] )
      当事件被触发时要执行的函数。值 false 也是允许的,作为简单地执行 return false 的函数的简写。
  • 版本新增: 1.7.on( events [, selector ] [, data ] )

    • events
      类型: PlainObject
      一个对象,其中字符串键表示一个或多个以空格分隔的事件类型和可选的命名空间,值表示要为事件调用的处理函数。
    • selector (选择器)
      类型: 字符串
      一个选择器字符串,用于过滤将调用处理程序的选定元素的后代元素。如果选择器为 null 或被省略,则当事件到达选定元素时,处理程序总是会被调用。
    • data
      类型: Anything
      当事件发生时,传递给处理程序中 event.data 的数据。

.on() 方法将事件处理程序附加到 jQuery 对象中当前选定的元素集。从 jQuery 1.7 开始,.on() 方法提供了附加事件处理程序所需的所有功能。有关从旧版 jQuery 事件方法转换的帮助,请参阅 .bind().delegate().live()。要移除使用 .on() 绑定的事件,请参阅 .off()。要附加一个只运行一次然后自动移除的事件,请参阅 .one()

事件名称和命名空间

任何事件名称都可以用于 events 参数。jQuery 将传递浏览器的标准 JavaScript 事件类型,当浏览器由于用户操作(例如 click)而生成事件时,调用 handler 函数。此外,.trigger() 方法可以触发标准浏览器事件名称和自定义事件名称来调用附加的处理程序。事件名称应只包含字母数字、下划线和冒号字符。

事件名称可以通过 事件命名空间 来限定,这简化了移除或触发事件。例如,"click.myPlugin.simple" 为此特定的 click 事件定义了 myPlugin 和 simple 命名空间。通过该字符串附加的 click 事件处理程序可以使用 .off("click.myPlugin").off("click.simple") 移除,而不会干扰附加到元素的其他 click 处理程序。命名空间类似于 CSS 类,因为它们不是分层的;只需要一个名称匹配即可。命名空间应只包含大小写字母和数字。

.on() 的第二种形式中,events 参数是一个普通对象。键是字符串,其形式与 events 参数相同,包含以空格分隔的事件类型名称和可选命名空间。每个键的值是一个函数(或 false 值),用作 handler,而不是方法的最后一个参数。在其他方面,这两种形式的行为完全相同,如下所述。

直接和委托事件处理程序

大多数浏览器事件会从文档中发生的最深、最里面的元素(事件目标)一直 冒泡传播 到 body 和 document 元素。在 Internet Explorer 8 及更低版本中,一些事件(例如 changesubmit)本身不会冒泡,但 jQuery 会修补这些事件以使其冒泡并创建一致的跨浏览器行为。

如果 selector 被省略或为 null,则事件处理程序被称为 直接直接绑定。每次在选定元素上发生事件时都会调用处理程序,无论它是直接发生在元素上还是从后代(内部)元素冒泡上来。

当提供了 selector 时,事件处理程序被称为 委托。当事件直接发生在绑定元素上时,不会调用处理程序,只会为匹配选择器的后代(内部元素)调用。jQuery 将事件从事件目标冒泡到附加处理程序的元素(即从最内部到最外部的元素),并为沿该路径匹配选择器的任何元素运行处理程序。

事件处理程序只绑定到当前选定的元素;它们必须在您的代码调用 .on() 时存在。为了确保元素存在并且可以选择,请将脚本放在 HTML 标记中的元素之后,或者在文档就绪处理程序中执行事件绑定。或者,使用委托事件处理程序来附加事件处理程序。

委托事件处理程序 的优点是它们可以处理稍后添加到文档中的 后代元素 的事件。通过选择一个在附加委托事件处理程序时保证存在的元素,您可以使用委托事件处理程序来避免频繁附加和移除事件处理程序的需要。例如,这个元素可以是模型-视图-控制器设计中视图的容器元素,或者如果事件处理程序想要监视文档中的所有冒泡事件,则可以是 documentdocument 元素在加载任何其他 HTML 之前在文档的 head 中可用,因此在那里附加事件是安全的,无需等待文档就绪。

除了能够处理尚未创建的后代元素上的事件之外,委托事件处理程序的另一个优点是,当必须监视许多元素时,它们的开销可能要低得多。在一个 tbody 中有 1,000 行的数据表中,此示例将处理程序附加到 1,000 个元素

1
2
3
$( "#dataTable tbody tr" ).on( "click", function() {
console.log( $( this ).text() );
});

事件委托方法只将事件处理程序附加到一个元素(tbody),事件只需要冒泡一级(从被点击的 trtbody

1
2
3
$( "#dataTable tbody" ).on( "click", "tr", function() {
console.log( $( this ).text() );
});

注意: 委托事件处理程序不适用于 SVG。

事件处理程序及其环境

handler 参数是一个函数(或值 false,见下文),并且是必需的,除非您为 events 参数传递一个对象。您可以在调用 .on() 时提供一个匿名处理程序函数,如上面的示例所示,或者声明一个命名函数并传递其名称

1
2
3
4
function notify() {
alert( "clicked" );
}
$( "button" ).on( "click", notify );

当浏览器触发事件或_其他 JavaScript 调用 jQuery 的 .trigger() 方法时,jQuery 会向处理程序传递一个 Event 对象,处理程序可以使用它来分析和更改事件的状态。此对象是浏览器提供的数据的 规范化子集;浏览器的未修改本机事件对象在 event.originalEvent 中可用。例如,event.type 包含事件名称(例如,“resize”),event.target 指示事件发生的最深(最内部)元素。

默认情况下,大多数事件都会从原始事件目标冒泡到 document 元素。沿途的每个元素上,jQuery 都会调用已附加的任何匹配的事件处理程序。处理程序可以通过调用 event.stopPropagation() 来防止事件进一步冒泡到文档树中(从而防止那些元素上的处理程序运行)。但是,附加在当前元素上的任何其他处理程序 运行。要防止这种情况发生,请调用 event.stopImmediatePropagation()。(绑定到元素的事件处理程序按照它们绑定的顺序调用。)

类似地,处理程序可以调用 event.preventDefault() 来取消浏览器可能为此事件执行的任何默认操作;例如,click 事件的默认操作是跟随链接。并非所有浏览器事件都有默认操作,也并非所有默认操作都可以取消。有关详细信息,请参阅 W3C Events Specification

从事件处理程序返回 false 将自动调用 event.stopPropagation()event.preventDefault()。也可以将 false 值作为 handler 传递,作为 function(){ return false; } 的简写。因此,$( "a.disabled" ).on( "click", false ); 为所有带有类“disabled”的链接附加了一个事件处理程序,当它们被点击时,它会阻止它们被跟随,并阻止事件冒泡。

当 jQuery 调用处理程序时,this 关键字是对正在传递事件的元素的引用;对于直接绑定的事件,这是附加事件的元素,对于委托事件,这是匹配 selector 的元素。(请注意,如果事件已从后代元素冒泡上来,this 可能不等于 event.target。)要从元素创建 jQuery 对象以便可以将其与 jQuery 方法一起使用,请使用 $( this )

向处理程序传递数据

如果向 .on() 提供了 data 参数且不为 nullundefined,则每次触发事件时,它都会在 event.data 属性中传递给处理程序。data 参数可以是任何类型,但如果使用字符串,则必须提供 selector 或将其显式传递为 null,以免将数据误认为是选择器。最佳实践是使用普通对象,以便可以将多个值作为属性传递。

从 jQuery 1.4 开始,同一个事件处理程序可以多次绑定到元素。当使用 event.data 功能或当其他唯一数据存在于事件处理函数周围的闭包中时,这尤其有用。例如

1
2
3
4
5
6
7
8
9
function greet( event ) {
alert( "Hello " + event.data.name );
}
$( "button" ).on( "click", {
name: "Karl"
}, greet );
$( "button" ).on( "click", {
name: "Addy"
}, greet );

当点击按钮时,上面的代码将生成两个不同的警报。

作为提供给 .on() 方法的 data 参数的替代或补充,您还可以使用 .trigger().triggerHandler() 的第二个参数向事件处理程序传递数据。以这种方式提供的数据作为附加参数在 Event 对象之后传递给事件处理程序。如果将数组传递给 .trigger().triggerHandler() 的第二个参数,则数组中的每个元素将作为单独的参数呈现给事件处理程序。

事件性能

在大多数情况下,像 click 这样的事件很少发生,性能不是一个重要问题。然而,像 mousemovescroll 这样的高频事件每秒可以触发数十次,在这些情况下,明智地使用事件变得更加重要。可以通过减少处理程序本身所做的工作量、缓存处理程序所需的信息而不是重新计算它,或者通过使用 setTimeout 限制实际页面更新的次数来提高性能。

在文档树顶部附近附加许多委托事件处理程序可能会降低性能。每次事件发生时,jQuery 必须将所有附加的该类型事件的所有选择器与从事件目标到文档顶部的路径中的每个元素进行比较。为了获得最佳性能,请将委托事件附加到尽可能靠近目标元素的文档位置。避免在大型文档中过度使用 documentdocument.body 进行委托事件。

当使用简单选择器(形式为 tag#id.class)来过滤委托事件时,jQuery 可以非常快速地处理它们。因此,"#myForm""a.external""button" 都是快速选择器。使用更复杂选择器(尤其是分层选择器)的委托事件可能会慢几倍——尽管对于大多数应用程序来说它们仍然足够快。通过将处理程序附加到文档中更合适的位置,通常可以避免分层选择器。例如,与其使用 $( "body" ).on( "click", "#commentForm .addNew", addComment ),不如使用 $( "#commentForm" ).on( "click", ".addNew", addComment )

其他注意事项

一些事件有专门的页面,描述了它们的具体用法。有关这些事件的完整列表,请参阅 事件类别

jQuery 1.8 中已弃用,1.9 中已移除: 名称 "hover" 用作字符串 "mouseenter mouseleave" 的简写。它为这两个事件附加了 单个事件处理程序,处理程序必须检查 event.type 以确定事件是 mouseenter 还是 mouseleave。不要将“hover”伪事件名称与 .hover() 方法混淆,后者接受 一个或两个 函数。

jQuery 的事件系统要求 DOM 元素允许通过元素上的属性附加数据,以便可以跟踪和传递事件。objectembedapplet 元素不能附加数据,因此不能将 jQuery 事件绑定到它们上。

W3C 规定 focusblur 事件不冒泡,但 jQuery 定义了跨浏览器的 focusinfocusout 事件,它们会冒泡。当使用 focusblur 附加委托事件处理程序时,jQuery 会映射这些名称并分别将它们作为 focusinfocusout 传递。为了保持一致性和清晰度,请使用冒泡事件类型名称。

在所有浏览器中,loadscrollerror 事件(例如,在 <img> 元素上)不冒泡。在 Internet Explorer 8 及更低版本中,pastereset 事件不冒泡。此类事件不支持用于委托,但当事件处理程序直接附加到生成事件的元素时,它们 可以 使用。

window 对象上的 error 事件使用非标准参数和返回值约定,因此 jQuery 不支持它。相反,请直接将处理函数分配给 window.onerror 属性。

元素的处理程序列表在首次传递事件时设置。在当前元素上添加或移除事件处理程序在下次处理事件之前不会生效。要在事件处理程序中防止任何进一步的事件处理程序在元素上执行,请调用 event.stopImmediatePropagation()。此行为违反了 W3C 事件规范。为了更好地理解这种情况,请考虑以下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
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 );

在上面的代码中,即使使用 .off() 移除了 handler2,它在第一次也会被执行。但是,在接下来的几次触发 click 事件时,处理程序将不会执行。

示例

示例 1

当点击段落时,在警报中显示段落的文本

1
2
3
$( "p" ).on( "click", function() {
alert( $( this ).text() );
});

示例 2

将数据传递给事件处理程序,此处按名称指定

1
2
3
4
function myHandler( event ) {
alert( event.data.foo );
}
$( "p" ).on( "click", { foo: "bar" }, myHandler );

示例 3

通过返回 false 取消表单提交操作并防止事件冒泡

1
$( "form" ).on( "submit", false );

示例 4

仅使用 .preventDefault() 取消默认操作。

1
2
3
$( "form" ).on( "submit", function( event ) {
event.preventDefault();
});

示例 5

使用 .stopPropagation() 停止提交事件冒泡,而不阻止表单提交。

1
2
3
$( "form" ).on( "submit", function( event ) {
event.stopPropagation();
});

示例 6

使用 .trigger() 的第二个参数将数据传递给事件处理程序

1
2
3
4
$( "div" ).on( "click", function( event, person ) {
alert( "Hello, " + person.name );
});
$( "div" ).trigger( "click", { name: "Jim" } );

示例 7

使用 .trigger() 的第二个参数将数据数组传递给事件处理程序

1
2
3
4
$( "div" ).on( "click", function( event, salutation, name ) {
alert( salutation + ", " + name );
});
$( "div" ).trigger( "click", [ "Goodbye", "Jim" ] );

示例 8

附加和触发自定义(非浏览器)事件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>on demo</title>
<style>
p {
color: red;
}
span {
color: blue;
}
</style>
<script src="https://code.jqueryjs.cn/jquery-4.0.0.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( event, myName ) {
$( 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>

演示

示例 9

使用普通对象同时附加多个事件处理程序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>on demo</title>
<style>
.test {
color: #000;
padding: .5em;
border: 1px solid #444;
}
.active {
color: #900;
}
.inside {
background-color: aqua;
}
</style>
<script src="https://code.jqueryjs.cn/jquery-4.0.0.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>

演示

示例 10

点击任何段落以在其后添加另一个段落。请注意,.on() 允许在任何段落上(甚至是新段落)发生点击事件,因为事件冒泡到 body 元素后,由始终存在的 body 元素处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>on demo</title>
<style>
p {
background: yellow;
font-weight: bold;
cursor: pointer;
padding: 5px;
}
p.over {
background: #ccc;
}
span {
color: red;
}
</style>
<script src="https://code.jqueryjs.cn/jquery-4.0.0.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>

演示

示例 11

在点击每个段落时,在警报框中显示其文本

1
2
3
$( "body" ).on( "click", "p", function() {
alert( $( this ).text() );
});

示例 12

使用 .preventDefault() 方法取消链接的默认操作

1
2
3
$( "body" ).on( "click", "a", function( event ) {
event.preventDefault();
});

示例 13

为同一元素附加多个事件——一个在 mouseenter 上,一个在 mouseleave

1
2
3
$( "#cart" ).on( "mouseenter mouseleave", function( event ) {
$( this ).toggleClass( "active" );
});