日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

jQuery-1.9.1源码分析系列(十) 事件系统——事件绑定

發布時間:2023/12/9 windows 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jQuery-1.9.1源码分析系列(十) 事件系统——事件绑定 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

  事件綁定的方式有很多種。使用了jQuery那么原來那種綁定方式(elem.click = function(){...})就不推薦了,原因?

  最主要的一個原因是elem.click = fn這種方式只能綁定一個事件處理,多次綁定的只會保留最后一次綁定的結果。

  

  看一下jQuery綁定事件的方式有哪些

jQuery.fn.eventType([[data,]?fn])

  比如eventType指的是事件類型,比如click: $("#chua").click(fn);

  data這個參數一般都不會使用。這種方式事件綁定在("#chua")上,沒有委托事件,和js原生的事件綁定更接近。我們看一下源碼

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 ) {//合并15種事件統一增加到jQuery.fn上,內部調用this.on / this.triggerjQuery.fn[ name ] = function( data, fn ) {return arguments.length > 0 ?this.on( name, null, data, fn ) ://如果不帶參數表示立刻觸發指定事件this.trigger( name );}; });

?

jQuery.fn.bind( types[, data], fn )

  比如$("#chua").bind("click",fn)。直接將事件綁定到$("#chua")上,沒有委托事件。源碼

bind: function( types, data, fn ) {return this.on( types, null, data, fn ); }, unbind: function( types, fn ) {return this.off( types, null, fn ); }

?

jQuery.fn.delegate(selector, types[, data], fn)

  顧名思義delegate這個函數是用來做事件委托的,將選擇器selector對應的響應處理委托給當前jQuery所匹配的元素。

  比如:$(document).delegate('#big',"click",dohander);分析到這里順便分析一下事件委托的處理流程。

  當點擊"#big"元素的時候,事件click會冒泡直到document節點;

  document綁定了處理事件,這個處理事件會調用到事件分發器dispatch;

  dispatch中取出對應事件類型click的所有的委托事件列表handlers;

  根據事件源event.target過濾出委托事件列表handlers中每一個元素的selector屬性對應的節點處于事件原和委托節點document之間(包括事件源)的委托事件,保存為handlerQueue;

  執行handlerQueue里面的事件處理。

  上面是一個大致的流程,后續會詳細分析。先看delegate源碼

delegate: function( selector, types, data, fn ) {return this.on( types, selector, data, fn ); }, undelegate: function( selector, types, fn ) {// ( namespace ) or ( selector, types [, fn] )return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn ); }

?

jQuery.fn.one( types[, selector[, data]], fn )

  通過one()函數綁定的事件處理函數都是一次性的,只有首次觸發事件時會執行該事件處理函數。觸發之后,jQuery就會移除當前事件綁定。

  比如$("#chua").one("click",fn);為#chua節點綁定一次性的click事件

  $(document).one("click","#chua",fn);將#chua的click事件委托給document處理。源碼

one: function( types, selector, data, fn ) {return this.on( types, selector, data, fn, 1 ); }

?

jQuery.fn.trigger(type[, data])

jQuery.fn.triggerHandler(type[, data])

  trigger觸發jQuery對象所匹配的每一個元素對應type類型的事件。比如$("#chua").trigger("click");

  triggeHandler只觸發jQuery對象所匹配的元素中的第一個元素對應的type類型的事件,且不會觸發事件的默認行為。

//立刻觸發jQuery對象內所有元素的指定type的事件 trigger: function( type, data ) {return this.each(function() {jQuery.event.trigger( type, data, this );}); }, //立刻觸發jQuery對象內第一個元素的指定type的事件,且不會觸發事件(比如表單提交)的默認行為 triggerHandler: function( type, data ) {var elem = this[0];if ( elem ) {return jQuery.event.trigger( type, data, elem, true );} }

  

  上面分析了那么些個事件綁定,有么有發現他們都是使用.on方式綁定的?這也是為什么提倡統一使用on來綁定的原因(one方式除外)。

jQuery.fn.on( types[, selector[, data]], fn )

  .on的事件綁定一半的代碼都實在處理傳遞不同參數的處理,這也是jQuery的口號Write less, do more的代價吧。最終使用jQuery.event.add來綁定事件。

  jQuery.event.add綁定事件有幾個比較關鍵的地方:

  第一個,使用內部緩存來保存節點elem的事件信息

//獲取緩存數據
       elemData = jQuery._data( elem );...
       
       //設置緩存數據
if ( !(events = elemData.events) ) {events = elemData.events = {};}if ( !(eventHandle = elemData.handle) ) {eventHandle = elemData.handle = function( e ) {...};//將elem作為handle函數的一個特征防止ie非本地事件引起的內存泄露eventHandle.elem = elem;}

  第二個,設置綁定事件信息,特別是指定的選擇器selector、響應處理handler、響應事件類型type、命名空間namespace

// handleObj:設置綁定事件信息。貫穿整個事件處理handleObj = jQuery.extend({type: type,origType: origType,data: data,handler: handler,guid: handler.guid,selector: selector,// For use in libraries implementing .is(). We use this for POS matching in `select`//"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +//whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )//用來判斷親密關系needsContext: selector && jQuery.expr.match.needsContext.test( selector ),namespace: namespaces.join(".")}, handleObjIn );

  第三個,節點的事件列表中,真正的委托事件列表放置在前面,和delegateCount屬性同步,即events.click.length假設為3,events.click.delegateCount假設為2。那么events.click[0]和events.click[1]所指定事件是委托事件。第三個events.click[2]對應的事件不是委托事件,而是節點自身的事件。

//將事件對象handleObj添加到元素的處理列表,委托事件放在前面,委托代理計數遞增if ( selector ) {handlers.splice( handlers.delegateCount++, 0, handleObj );} else {handlers.push( handleObj );}

  源碼和添加事件后的結構上一章已經分析,詳情請點擊查看

  

  綁定有一個公用函數jQuery.fn.on。解綁同樣有一個公用函數jQuery.fn.off

jQuery.fn.off([ types[, selector][, fn]] )

  這里的傳參有個比較特殊的情況:當types是瀏覽器事件對象event的時候,表示要去掉(解綁)委托節點上event.selector指定的委托事件

//傳入的參數是事件且綁定了處理函數 if ( types && types.preventDefault && types.handleObj ) {// ( event ) dispatched jQuery.EventhandleObj = types.handleObj;//types.delegateTarget是事件托管對象 jQuery( types.delegateTarget ).off(//組合jQuery識別的typehandleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,handleObj.selector,handleObj.handler);return this; }

  無論如何最終都是調用jQuery.event.remove函數來解綁事件。

  jQuery.fn.off完整的源碼如下

off: function( types, selector, fn ) {var handleObj, type;//傳入的參數是事件且綁定了處理函數if ( types && types.preventDefault && types.handleObj ) {// ( event ) dispatched jQuery.EventhandleObj = types.handleObj;//types.delegateTarget是事件托管對象 jQuery( types.delegateTarget ).off(//組合jQuery識別的typehandleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,handleObj.selector,handleObj.handler);return this;}if ( typeof types === "object" ) {// ( types-object [, selector] )for ( type in types ) {this.off( type, selector, types[ type ] );}return this;}if ( selector === false || typeof selector === "function" ) {// ( types [, fn] )fn = selector;selector = undefined;}if ( fn === false ) {fn = returnFalse;}return this.each(function() {jQuery.event.remove( this, types, fn, selector );}); } View Code

  

  接下來分析一下事件解綁的低級api?jQuery.event.remove。

jQuery.event.remove

  jQuery使用.off()函數傷處綁定的事件時內部調用的基礎函數是jQuery.event.remove。該函數的處理流程如下

  1.?分解傳入的要刪除的事件類型types,遍歷類型,如果要刪除的事件沒有事件名,只有命名空間則表示刪除該命名空間下所有綁定事件

//分解types為type.namespace為單位元素的數組 types = ( types || "" ).match( core_rnotwhite ) || [""]; t = types.length; while ( t-- ) {tmp = rtypenamespace.exec( types[t] ) || [];type = origType = tmp[1];namespaces = ( tmp[2] || "" ).split( "." ).sort(); //解綁當前元素的當前命名空間(types[ t ])上所有的事件if ( !type ) {for ( type in events ) {jQuery.event.remove( elem, type + types[ t ], handler, selector, true );}continue;}...

  2.?遍歷類型過程中,刪除匹配的事件,代理計數修正

type = ( selector ? special.delegateType : special.bindType ) || type; handlers = events[ type ] || []; tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );//刪除匹配事件 origCount = j = handlers.length; while ( j-- ) {handleObj = handlers[ j ]; //各種滿足移除事件的條件才能移除if ( ( mappedTypes || origType === handleObj.origType ) &&( !handler || handler.guid === handleObj.guid ) &&( !tmp || tmp.test( handleObj.namespace ) ) &&( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {handlers.splice( j, 1 );         if ( handleObj.selector ) {handlers.delegateCount--;}         if ( special.remove ) {special.remove.call( elem, handleObj );}} }

  3.?如果節點上指定類型的事件處理器已經為空,則將events上的該類型的事件處理對象移除

// 移除事件處理對象 // (移除特殊事件處理過程中避免潛在的無限遞歸,下一章會專門詳解這種情況) if ( origCount && !handlers.length ) { //例如 var js_obj = document.createElement("div"); js_obj.onclick = function(){ …} //上面的js_obj是一個DOM元素的引用,DOM元素它長期在網頁當中,不會消失,而這個DOM元素的一屬性onclick,又是內部的函數引用(閉包),而這個匿名函數又和js_obj之間有隱藏的關聯(作用域鏈)所以形成了一個,循環引用. if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {jQuery.removeEvent( elem, type, elemData.handle ); } delete events[ type ]; }

  4.?如果節點上沒有任何綁定的事件,則清空事件處理入口handle

if ( jQuery.isEmptyObject( events ) ) {   delete elemData.handle;   //removeData還檢事件對象是否為空,所以使用它替代deletejQuery._removeData( elem, "events" ); }

?

拓展: 瀏覽器事件刪除jQuery.removeEvent

jQuery.removeEvent = document.removeEventListener ? function( elem, type, handle ) {if ( elem.removeEventListener ) {elem.removeEventListener( type, handle, false );} } : function( elem, type, handle ) {var name = "on" + type;if ( elem.detachEvent ) {// #8545, #7054,避免自定義事件在IE6-8中的內存泄露// detachEvent需要傳遞第一個參數,不能是undefined的if ( typeof elem[ name ] === core_strundefined ) {elem[ name ] = null;}elem.detachEvent( name, handle );} };

?

?  如果覺得本文不錯,請點擊右下方【推薦】!

?

?

?

  

轉載于:https://www.cnblogs.com/chuaWeb/p/jQuery-1-9-1-addEvents-2.html

總結

以上是生活随笔為你收集整理的jQuery-1.9.1源码分析系列(十) 事件系统——事件绑定的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。