實體方法和便捷方法是指jQuery可以直接通過鏈接操作的方法,是通過呼叫$.event上的方法(上一節介紹的底層方法)來實作的,常用的如下:
- on(types,selector,data,fn,one) ;為匹配元素集合中的每個元素系結一個或多個型別的事件監聽函式
- types ;事件型別字串,多個事件型別之間用空格隔開
- selector ;可選,是一個選擇器運算式字串,用于系結代理事件,
- data ;傳遞給事件監聽函式的自定義資料,可以是任何型別,
- fn ;待系結的監聽函式
- one ;該事件是否只執行一次,為方法.one()提供支持
writer by:大沙漠 QQ:22969969
- off(types,selector,fn) ;移除匹配元素中每個元素上系結的一個或多個型別的監聽函式,引數如下:
- types ;一個或多個以空格分隔的事件型別和可選的命名空間
- selector ;可選的選擇器運算式字串,用于移除代理事件
- fn ;待移除的監聽函式,可以設定為false,表示內部定義的只回傳false的函式
- off(types,selector,fn) ;移除匹配元素中每個元素上系結的一個或多個型別的監聽函式
- types ;一個或多個以空格分隔的事件型別和可選的命名空間
- selector ;可選的選擇器運算式字串,用于移除代理事件
- fn ;待移除的監聽函式,可以設定為false
- bind(types,data,fn) ;系結一個普通事件
- trigger(type, data) 執行每個匹配元素上系結的監聽函式和默認行為,并模擬冒泡程序
- one(types,selector,data,fn) ;為匹配元素集合中的每個元素系結最多執行一次的事件監聽函式
- hover(fnOver, fnOut) ;用于在匹配元素上系結一個或兩個監聽函式,當滑鼠指標進入和離開時,系結的監聽函式被執行
我們還是以上一節的實體為例,用實體方法改寫一下,如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="http://libs.baidu.com/jquery/1.7.1/jquery.min.js"></script> <style>div{width: 200px;padding-top:50px;height: 150px;background: #ced;}div button{margin:0 auto;display: block;}</style> </head> <body> <div> <button id="button">按鈕1</button> </div> <script> $("div").on('click',()=>console.log('div普通單擊事件')); $('div').on('click','button',()=>console.log('d1代理事件')) </script> </body> </html>
渲染如下:

和上一節一樣,我們在div上系結了一個普通事件和代理事件,當點擊div時觸發普通事件,點擊按鈕時分別觸發普通事件和代理事件,
另外為了更方變使用事件,jQuery還定義了很多的便捷事件方法,可以直接在jQuery實體上呼叫,注意:便捷方法不能系結代理事件,只能系結普通事件,所有的便捷方法如下:
blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu
我們將上面的例子改寫一下,用便捷方法來實作,如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="http://libs.baidu.com/jquery/1.7.1/jquery.min.js"></script> <style>div{width: 200px;padding-top:50px;height: 150px;background: #ced;}div button{margin:0 auto;display: block;}</style> </head> <body> <div> <button id="button">按鈕1</button> </div> <script> $("div").click(()=>console.log('div普通單擊事件')); //用便捷事件來實作 $('div').on('click','button',()=>console.log('d1代理事件')) //代理事件不能用便捷方法來操作,因此我們用實體方法來實作 </script> </body> </html>
效果和上面是一樣的,
原始碼分析
實體方法是定義在jQuery.fn上的,on主要對引數做一些判斷,以支持多種格式的呼叫方法,實作如下:
jQuery.fn.extend({ on: function( types, selector, data, fn, /*INTERNAL*/ one ) { //該方法主要是修正引數,為匹配元素集合中的每個元素系結一個或多個型別的事件監聽函式, var origFn, type; // Types can be a map of types/handlers //如果types是物件時,即引數格式是.on(Object,selector,data,one)或.one(Object,data,one)則 if ( typeof types === "object" ) { // ( types-Object, selector, data ) if ( typeof selector !== "string" ) { // ( types-Object, data ) data =https://www.cnblogs.com/greatdesert/p/ selector; selector = undefined; } for ( type in types ) { //遍歷引數types,遞回呼叫方法.on(types,selector,data,fn,one)系結事件, this.on( type, selector, data, types[ type ], one ); } return this; } if ( data =https://www.cnblogs.com/greatdesert/p/= null && fn == null ) { //如果沒有引數3、4,則認為格式是.on(types,fn) // ( types, fn ) fn = selector; //把第二個引數修正為fn, data = https://www.cnblogs.com/greatdesert/p/selector = undefined; } else if ( fn == null ) { //傳入了三個引數時 if ( typeof selector === "string" ) { //如果第二個引數是字串,則認為格式是:.on(types,selector,fn) 忽略引數data,并把第三個引數作為引數fn, // ( types, selector, fn ) fn = data; data = undefined; } else { //否則則認為忽略引數selector,并把第而個引數作為引數data,并把第三個引數作為引數fn,格式是.on(types,data,fn) // ( types, data, fn ) fn = data; data = selector; selector = undefined; } } if ( fn === false ) { //如果引數fn是布林值false,則把它修正為總回傳false的函式returnFalse(), fn = returnFalse; } else if ( !fn ) { //如果fn沒有值則直接回傳, return this; } if ( one === 1 ) { //當方法one()呼叫.on()時,該引數為1,就會把監聽函式fn重新封裝為一個只會執行一次的新監聽函式, origFn = fn; fn = function( event ) { // Can use an empty set, since event contains the info jQuery().off( event ); return origFn.apply( this, arguments ); }; // Use same guid so caller can remove using origFn fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); } return this.each( function() { //遍歷當前的this jQuery.event.add( this, types, fn, data, selector ); //呼叫add()系結事件 }); }, one: function( types, selector, data, fn ) { //為匹配元素集合中的每個元素系結一個或多個型別的事件監聽函式,每個監聽函式在每個匹配元素上最多執行一次,該方法簡單的通過呼叫.on(types,selector,data,fn,one)來實作, return this.on.call( this, types, selector, data, fn, 1 ); }, /*略*/ })
對于便捷方法來說,他就是在$.fn上定義每一個屬性,值為一個函式,內部還是呼叫$.fn.on來實作添加事件的,如下:
jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
"change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { //引數1是一個陣列 引數2是個函式,其中name是值,比如blur、focus
// Handle event binding
jQuery.fn[ name ] = function( data, fn ) { //初始化事件便捷方法,在jQuery.fn物件上添加元素,這樣jQuery實體就可以直接訪問了
if ( fn == null ) { //修正引數,如果只傳入一個引數,則把該引數視為fn引數,把data視為null
fn = data;
data = null;
}
return arguments.length > 0 ? //根據引數個數決定是系結事件還是觸發事件
this.on( name, null, data, fn ) : //如果引數個數大于1,則呼叫方法.on()系結事件監聽函式
this.trigger( name ); //如果沒有引數,則呼叫方法.trigger()觸發事件監聽函式和默認行為
};
if ( jQuery.attrFn ) { //記錄事件便捷方法名,在呼叫jQuery.attr()讀取或設定HTML屬性時,如果屬性名與事件便捷方法名同名,則會改為呼叫同名的事件便捷方法a
jQuery.attrFn[ name ] = true;
}
if ( rkeyEvent.test( name ) ) {
jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;
}
if ( rmouseEvent.test( name ) ) {
jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;
}
});
可以看到,如果執行便捷方法時不傳遞引數將觸發該事件,例如:$('div').click()將會觸發在該div上系結的普通事件,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/34142.html
標籤:jQuery
