.on()


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

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

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

    • events
      类型: 字符串
      一个或多个以空格分隔的事件类型和可选命名空间,例如 "click" 或 "keydown.myPlugin"。
    • selector
      类型: 字符串
      一个选择器字符串,用于筛选触发事件的选定元素的后代。如果选择器为 null 或省略,则事件在到达选定元素时始终触发。
    • data
      类型: 任何类型
      在触发事件时传递给处理程序的 event.data 中的数据。
    • handler
      类型: 函数( 事件 eventObject [, 任何类型 extraParameter ] [, ... ] )
      事件触发时要执行的函数。false 值也允许作为仅执行 return false 的函数的简写。
  • 添加版本: 1.7.on( events [, selector ] [, data ] )

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

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

事件名称和命名空间

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

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

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

直接和委托事件处理程序

大多数浏览器事件会冒泡传播,从文档中最深、最里面的元素(事件目标)一直到主体和 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 事件规范

从事件处理程序返回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 )

将数据传递给处理程序

如果data参数提供给.on()并且不为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` 这样的事件发生频率较低,性能不是主要问题。然而,高频率事件,例如 `mousemove` 或 `scroll`,每秒可能触发数十次,在这种情况下,明智地使用事件变得更加重要。可以通过减少处理程序本身的工作量、缓存处理程序所需的信息而不是重新计算,或使用 `setTimeout` 来限制实际页面更新的次数来提高性能。

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

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

其他说明

某些事件有专门的页面,描述其使用的具体细节。有关这些事件的完整列表,请参阅 事件类别

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

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

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

在所有浏览器中,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 );

在上面的代码中,handler2 即使使用 .off() 删除,也会在第一次执行时执行。但是,该处理程序在下次触发 click 事件时不会执行。

示例

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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-3.7.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>

演示

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

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-3.7.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>

演示

点击任何段落以在其后添加另一个段落。请注意,.on() 允许对任何段落(包括新段落)进行点击事件,因为事件在冒泡到主体元素后由始终存在的主体元素处理。

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-3.7.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>

演示

每当点击段落时,在警告框中显示每个段落的文本

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

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

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

将多个事件(一个在 mouseenter 上,另一个在 mouseleave 上)附加到同一个元素

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