on()
在选定的元素上绑定一个或多个事件处理函数。
.on(events[, selector ][, data ], handler(eventObject))
- events类型: String。一个或多个空格分隔的事件类型和可选的命名空间,或仅仅是命名空间,比如"click","keydown.myPlugin",或者".myPlugin"。
- selector类型: String。一个选择器字符串,用于过滤出被选中的元素中能触发事件的后代元素。如果选择器是
null
或者忽略了该选择器,那么被选中的元素总是能触发事件。 - data类型: Anything。当一个事件被触发时,要传递给事件处理函数的
event.data
。 - handler(eventObject)类型: Function()事件被触发时,执行的函数。若该函数只是要执行
return false
的话,那么该参数位置可以直接简写成false
。
.on(events[, selector ][, data ])
- events类型: PlainObject。一个对象,键是由一个或多个由空格分隔的事件类型及可选的名字空间,值是这些事件类型所对应的事件处理函数。
- selector类型: String。一个选择器字符串,用于过滤出被选中的元素中能触发事件的后代元素。如果选择器是
null
或者忽略了该选择器,那么被选中的元素总是能触发事件。 - data类型: Anything。当一个事件被触发时,要传递给事件处理函数的
event.data
。
.on()
方法事件处理程序到当前选定的jQuery对象中的元素。在jQuery 1.7中,.on()
方法提供绑定事件处理的所有功能。为了帮助从旧的jQuery事件方法转换过来,查看.bind()
,.delegate()
,和.live()
.要删除的.on()
绑定的事件,请参阅.off()
。要绑定一个事件,并且只运行一次,然后删除自己,请参阅.one()
on()可以绑定的事件
表单事件 | blur ,focus ,focusin ,focusout ,change ,select ,submit |
浏览器事件 | resize ,scroll |
鼠标事件 | click ,dblclick ,contextmenu |
键盘事件 | mousedown ,mouseup ,mousemove ,mouseover ,mouseout ,mouseenter ,mouseleave ,keydown ,keypress ,keyup |
自定义 | 事件名称和命名空间 |
Event names and namespaces(事件名称和命名空间)
任何事件的名称,可以作为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
参数,但是该值并不是方法中的最后一个参数。在其它方面,这两种形式在下面描述的内容中其行为都是相同的。如下所述。
Direct and delegated events(直接和委托的事件)
大多数浏览器事件冒泡,或者传播,都是由内到外的,从在文档最深处的元素(事件目标 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.
The event handler and its environment(事件处理程序和它的环境)
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)
。
Passing data to the handler(将数据传递到处理程序)
如果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())
Event performance(事件性能)
在大多数情况下,一个事件如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)
。
Additional notes(其他注意事项)
有一些事件的速记方法比如.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
事件被触发时将不执行。(注:查看代码运行效果:http://jsfiddle.net/feiwen8772/dgxru81d/)
例子
当点击段落时,显示该段落中的文本:
$("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(); });
传递一个data数据给.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://www.lanmper.cn/static/js/jquery-3.5.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>
使用对象同时添加多个事件处理函数。
<!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://www.lanmper.cn/static/js/jquery-3.5.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()
会为任何段落添加事件,包括新生成的段落,因为当事件冒泡到已经存在的 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://www.lanmper.cn/static/js/jquery-3.5.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>
当点击段落时,显示该段落中的文本:
$("body").on("click", "p",function (){ alert( $(this ).text() ); });
使用 preventDefault 方法,取消链接的默认动作。
$("body").on("click", "a",function (event){ event.preventDefault(); });
在同一个元素上绑定多个事件,一个mouseenter
和mouseleave
:
$( "#cart" ).on( "mouseenter mouseleave",function ( event ) { $(this ).toggleClass( "active" ); });