.on()
.on( events [, selector ] [, data ], handler )
描述:针对选中的元素,把一个事件处理函数附加到一个或多个事件上。
- events类型:String一个或更多的用空格分隔的事件类型,以及可选的命名空间,比如说"click"或者"keydown.myPlugin"。
- selector类型:String一个选择器字符串,用来筛选选中的触发事件的元素的后代元素I如果选择器是null,或者被省略,事件总是会在它抵达选中的元素时触发。
- data类型:Anything当一个事件被触发时,在
event.data
中传递给处理函数的数据。 - handler一个函数,在触发事件时执行它。还允许用false值,作为只做
return false
的函数的简写。
- events类型:PlainObject个对象,在那里,字符串键代表一个或多个空格隔开的事件类型,以及可选的命名空间;值代表针对事件调用的处理函数。
- selector类型:String一个选择器字符串,用于筛选出被选中的元素中能触发事件的后代元素。如果选择器是null或者省略了该选择器,将会在事件抵达选中的元素时调用处理函数。
- data类型:Anything当一个事件发生时,在
event.data
中传递给处理函数的数据。
.on()
方法把事件处理函数附加到当前选中的元素集合上。自从jQuery 1.7,.on()
方法提供了附加事件处理函数的所有的功能需要。为了帮助从旧的jQuery事件方法转换过来,参见.bind()
、.delegate()
和.live()
。要想删除作.on()
绑定的事件,参见.off()
。要想附加只运行一次就自动删除的事件,参见.one()
。
事件名和命名空间
任何事件名都可以用于events
参数。当浏览器生成用户操作产生的事件,比如说click
的时候,jQuery将传递入浏览器的标准JavaScript事件类型,调用handler
函数。另外,.trigger()
方法能够触发标准浏览器事件名,以及自定义事件名,以调用附加的处理函数。事件名必须只包含字母数字、下划线,以及冒号字符。
一个事件名可以添加指定的事件命名空间,以简化删除或触发该事件。举个例子,"click.myPlugin.simple"
为特定的点击事件定义了myPlugin命名空间和simple命名空间。通过那个字符串附加的点吉事件,可以用.off("click.myPlugin")
删除,不会干扰别的附加到该元素的点击事件处理函数。命名空间类似于CSS样式类,因为它们都是不分层次的;只需要匹配一个名字即可。以一个下划线开始的命名空间,是保留给jQuery用的。
在第二种.on()
形式中,events
参数是一个纯对象。它的键是一个字符吕,与events
参数的形式相同,是用空格隔开的事件类型名,以及可选的命名空间。每个键的值是一个函数(或者是false
值),用作handler
,代替该方法的最后一个参数。在其它方面,两种形式在它们的行为上是等同的,如下面的讲解。
直接事件和委托事件
主流浏览器事件的冒泡或者传播,发生在document中的最深、最内部的元素(event target)上,然后向上传播到body,以及document元素。在Internet Explorer 8以及更低的版本中,一些事件类型,比如说change
和submit
不能原生冒泡,但是jQuery弥补了冒泡功能,并创建了跨浏览器行为一致性。
如果省略了selector
,或者它被设置为null,则事件处理函数会被视为直接或者直接绑定。每当一个事件在选中的元素上发生时,就会调用该事件处理函数,无论它是直接发生在该元素上,还是发生在后代元素(内部元素)上。
如果提供了一个selector
,该事件处理函数会被视为委托事件。当事件直接在绑定的元素上发生时,不会调用处理函数,只有发生在匹配选择器的后代元素(内部元素)上时,才会调用处理函数。jQuery把事件从事件目标冒泡到附加了处理函数的元素上(亦即,从最内部的元素到最外层的元素),并运行处理函数。
事件处理函数只绑定到当前选中的元素上;他们必须在你调用.on()
的时候已经存在在网页上。为了确保元素存在,而且可以被选中,请把脚本放在HTML标签中的元素后面,或者在document.ready
处理函数内部实施一个事件绑定。作为替代,也可以使用委托事件以附加事件处理函数。
委托事件有这么一个好处,它们可以处理来自以后才添加到document的后代元素上的事件。 挑拣一个元素,保证是附加委托事件处理函数是已经存在的元素,你可以使用委托事件以避免频繁附加事件处理函数删除事件处理函数的需要。如果事件处理函数想要监视document中所有的冒泡事件,这个元素可以,比如说是一个MVC设计中的视图的容器元素,或者是document元素。在document的head
元素中,哪怕别的HTML还没有载入,document元素也是可用的,所以它可以安全地附加事件,而不需要等待document就绪。
除了它们能够处理还没有创建的后代元素上的事件,委托事件的另一个好处是,当有很多元素必须被监视时,它们潜在地降低了很多开销。在一个带有1000行内容的数据表格上,下面这个示例要把事件处理函数附加到1000个元素上:
$( "#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.originalEvent
中访问到。举个例子,event.type
包含了事件名(例如,“resize”)以及event.target
,它表示事件发生的最深(最内部)的元素。
默认情况下,大多数事件会从原始事件目标向上冒泡,冒泡到document元素。每个元素都沿着这条路,jQuery调用任何已经附加的匹配的事件处理函数一个事件处理函数通过调用event.stopPropagation()
方法,可以阻止事件进一步沿着DOM树向上冒泡(因此阻止了在上层元素上的处理函数的运行)。任何其它附加在当前元素上的事件处理函数还将继续运行。要想阻止这,请调用event.stopImmediatePropagation()
。绑定在元素上的事件处理函数被调用的顺序和它们被绑定的顺序时一样的。
类似地,一个处理函数可以调用event.preventDefault()
以取消浏览器设定给该事件的任何默认操作。举个例子,click
事件上的默认操作是打开这个链接。并非所有的浏览器事件都有默认操作,而且并非所有的默认操作都是可以被取消的。参见W3C事件规范文档以了解详情。
从一个事件处理函数上返回false会自动调用event.stopPropagation()
和event.preventDefault()
。传递给handler
的false值,是function(){ return false; }
的简写。因此,$( "a.disabled" ).on( "click", false );
向所有带样式类“disabled”的链接附加了一个事件处理函数,可以在它们被点击的时候,阻止它们被打开,并制止事件冒泡。
当jQuery调用一个处理函数时,this
关键词是一个对事件递送到的元素的引用。对于直接绑定的事件,这就是事件所附加的元素;对于委托事件,这是一个匹配selector
的元素。(注意,如果事件是从后代元素冒泡上来的,this
可能并不等同于event.target
。)要想从这个元素上创建一个jQuery对象,从而它可以使用jQuery方法,请使用$( this )
。
把数据传递给处理函数
如果向.on()
提供一个data
对象,它既不是null也不是undefined,每次触发事件时,它会传给event.data
中的处理函数。data
参数可以是任何类型,但是如果使用了一个字符串,必须要么提供selector
,要明确向它传递null,从页不会被错当成一个选择器。最佳实践是使用一个纯对象,从而多个值可以传为属性。
自从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()
方法的第二个参数。以这种方式提供的数据,是传递给事件处理函数,作为Event
对象后面的进一步参数。如果一个数组是传递给.trigger()
方法或.triggerHandler()
方法的第二个参数,数组中的每个元素将出现在事件处理函数中,作为一个独立的参数。
事件实施
在大多数情况下,一个事件,比如说click
发生得不太频繁,性能表现得不太明显。然而,高度频繁发生的事件,比如说mousemove
或者scroll
,可以每秒引发几十次,那样的放,明智地使用事件会变得很重要。可以采用如下的方法提高事件的性能:减少事件中的工作量、缓存处理函数需要用的信息,而不是重复计算它,或者使用setTimeout
方法限制的页面更新的实际次数。
在document树的顶层附近附加很多委托事件处理函数,也可能降低性能。每次事件发生时,jQuery必须比较从event.target
开始到文档顶层的路径中每一个元素上所有已附加事件的所有选择器。为了最佳的性能,应把委托事件附加在尽可能接近目标元素的document位置。在大型document中,应避免过度地使用document
或document.body
来委托事件。
当选择器用来筛选委托事件时,jQuery可以快速地处理tag#id.class
这种形式的简单的选择器。因此,"#myForm"
、"a.external"
和"button"
都是快速选择器。使用更复杂的选择器的委托事件,特别是使用层级选择器,可能会比较慢——虽然对于大多数应用程序来说,它们还是足够快的。通过把处理函数附加到document中更合适的点上,通常可以简单避免层级选择器。举个例子,不是用$( "body" ).on( "click", "#commentForm .addNew", addComment )
,而是用$( "#commentForm" ).on( "click", ".addNew", addComment )
。
其它说明
对于一些事件,还有它们的简写方法,比如说.click()
,可以用来附加事件或触发事件。要想完整地了解简写方法,请参阅events category。
.hover()
方法,在jQuery 1.8中被建议弃用,在jQuery 1.9中被删除,它被用作字符串"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
事件。为了一致性和清楚明白,请使用冒泡事件类型名。
在所有浏览器中,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
事件触发以后,事件处理函数就不能再度执行了。
示例
当点击一个段落文本的时候,在提醒框中显示该段落文本文件的内容。
$( "p" ).on( "click", function() { alert( $( this ).text() ); });
把数据传递给事件处理函数,它由事件名指定:
function myHandler( event ) { alert( event.data.foo ); } $( "p" ).on( "click", { foo: "bar" }, myHandler );
通过返回false取消一个表单提交操作,并阻止事件冒泡。
$( "form" ).on( "submit", false );
使用.preventDefault()
来取消默认操作。
$( "form" ).on( "submit", function( event ) { event.preventDefault(); });
使用.stopPropagation()
方法阻止提交事件冒泡,但是不妨碍表单提交。
$( "form" ).on( "submit", function( event ) { event.stopPropagation(); });
使用.trigger()
的第二个参数,把数据传递到事件处理函数。
$( "div" ).on( "click", function( event, person ) { alert( "Hello, " + person.name ); }); $( "div" ).trigger( "click", { name: "Jim" } );
使用.trigger()
的第二个参数以把一个数据的数组传递到事件处理函数。
$( "div" ).on( "click", function( event, salutation, name ) { alert( salutation + ", " + name ); }); $( "div" ).trigger( "click", [ "Goodbye", "Jim" ] );
附加自定义事件(非浏览器事件)并触发它。
<!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.jquery.com/jquery-1.10.2.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>
演示结果
使用一个纯对象,同时附加多个事件处理函数。
<!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.jquery.com/jquery-1.10.2.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元素处理的,事件会冒泡到body元素上。
<!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.jquery.com/jquery-1.10.2.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>
演示结果
当在一个段落文本上点击时,在提醒框中显示这个段落文本。
$( "body" ).on( "click", "p", function() { alert( $( this ).text() ); });
使用.preventDefault()
方法,取消一个链接的默认操作。
$( "body" ).on( "click", "a", function( event ) { event.preventDefault(); });