亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

jQuery 1.9.1源碼分析系列(十)事件系統之綁定事件

2019-11-20 11:14:13
字體:
來源:轉載
供稿:網友

事件綁定的方法有很多種,使用了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.trigger      jQuery.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.Event  handleObj = types.handleObj;  //types.delegateTarget是事件托管對象  jQuery( types.delegateTarget ).off(   //組合jQuery識別的type   handleObj.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.Event  handleObj = types.handleObj;  //types.delegateTarget是事件托管對象  jQuery( types.delegateTarget ).off(   //組合jQuery識別的type   handleObj.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 );  });}

  接下來分析一下事件解綁的低級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("http://.(?:.*//.|)") + "(//.|$)" );//刪除匹配事件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還檢事件對象是否為空,所以使用它替代delete  jQuery._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 );   }};

以上內容是小編給大家介紹的jQuery 1.9.1源碼分析系列(十)事件系統之綁定事件,希望大家喜歡。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品亚洲美女av网站| 精品久久久久久久久久久久久| 中文字幕亚洲一区二区三区五十路| 欧美极品少妇xxxxx| 国产精品一区二区久久久| 成人午夜在线观看| 尤物九九久久国产精品的分类| 久久久精品久久久久| 国产精品久久久久av| 亚洲永久在线观看| 欧美xxxx做受欧美.88| 成人情趣片在线观看免费| 国产精品偷伦免费视频观看的| 欧美成人h版在线观看| 日韩网站免费观看高清| 国产中文字幕亚洲| 欧美视频中文在线看| 欧美激情一级精品国产| 国产精品视频久久| 欧美久久精品午夜青青大伊人| 久久中文久久字幕| y97精品国产97久久久久久| 91av在线精品| 日韩视频免费观看| 97超碰色婷婷| 97色在线播放视频| 欧美美女操人视频| 国产香蕉97碰碰久久人人| 中文字幕亚洲一区二区三区五十路| 国产精品美女久久久久久免费| 91成人在线播放| 欧美亚洲午夜视频在线观看| 永久免费精品影视网站| 国产成人精品a视频一区www| 日本精品性网站在线观看| 国产成人亚洲综合91| 国产成人综合精品| 日本精品性网站在线观看| 国产精品综合网站| 亚洲va欧美va国产综合剧情| 538国产精品一区二区免费视频| 日本精品性网站在线观看| 成人有码视频在线播放| 亚洲色图35p| 久久精品在线视频| 欧美午夜影院在线视频| 91久久久久久久一区二区| 国产精品久久久久久久久免费看| 久久久久久久久久久免费| 亚洲激情第一页| 国产精品久久色| 日本韩国欧美精品大片卡二| 欧美成人合集magnet| 在线视频欧美性高潮| 亚洲一区二区三区香蕉| 亚洲午夜性刺激影院| 成人免费xxxxx在线观看| 久久久久久尹人网香蕉| 在线观看国产精品日韩av| 亚洲国产精品va| 亚洲成人激情视频| 国产精品第10页| 亚洲精品视频在线播放| 国产婷婷成人久久av免费高清| 青青草原成人在线视频| 亚洲国产高清高潮精品美女| 91av国产在线| 国产精品久久久精品| 亚洲电影免费在线观看| 亚洲三级 欧美三级| 日韩国产一区三区| 在线观看精品自拍私拍| 久久91亚洲人成电影网站| 国产精品男人的天堂| 国产精品成人免费电影| 欧美日韩免费网站| 日韩小视频在线观看| 久久91亚洲精品中文字幕| 日韩av影片在线观看| 欧美激情一区二区三区久久久| 亚洲字幕一区二区| 国产精品久久综合av爱欲tv| 久久久久久噜噜噜久久久精品| 日韩高清中文字幕| 精品免费在线观看| 精品国产乱码久久久久久婷婷| 伊人久久综合97精品| 91地址最新发布| 欧美日韩亚洲一区二区三区| 中文国产亚洲喷潮| 亚洲精品一区中文| 久久久久久久久综合| 欧美精品videos性欧美| 久久色免费在线视频| 国产视频999| 欧美精品18videos性欧美| 97在线免费视频| 亚洲国模精品一区| 成人伊人精品色xxxx视频| 欧美性色视频在线| 97精品国产aⅴ7777| 91精品国产成人| 亚洲视频在线观看免费| 国产欧美日韩中文| 国产精品自拍网| 久青草国产97香蕉在线视频| 久久九九有精品国产23| 91久热免费在线视频| 欧美精品在线免费播放| 中文字幕日韩有码| 亚洲va久久久噜噜噜| 国产原创欧美精品| 日韩中文字幕在线看| 成人av在线网址| 日韩av免费在线播放| 欧美极品少妇xxxxⅹ免费视频| 亚洲四色影视在线观看| 午夜精品一区二区三区在线| 俺去亚洲欧洲欧美日韩| 亚洲天堂av女优| 亚洲精品天天看| 欧美国产日韩在线| 91av在线播放| 亚洲激情中文字幕| 精品免费在线视频| 国产成人精品久久久| 久久久久国产精品免费| 欧洲成人免费aa| 亚洲最大成人在线| 日韩av中文字幕在线播放| 亚洲级视频在线观看免费1级| 欧美另类极品videosbestfree| 午夜精品美女自拍福到在线| 国产一区二区三区久久精品| 亚洲已满18点击进入在线看片| 欧美日韩视频免费播放| 91地址最新发布| 日韩极品精品视频免费观看| 色狠狠久久aa北条麻妃| 性欧美视频videos6一9| 日韩精品在线影院| 欧美激情一区二区久久久| 精品久久久久久久久久| 久久精品国产久精国产一老狼| 自拍视频国产精品| 精品亚洲永久免费精品| 亚洲一区二区三区乱码aⅴ| 91精品久久久久久久久不口人| 久久视频在线免费观看| 成人黄色影片在线| 日韩在线观看免费全集电视剧网站| 亚洲国产精品人久久电影| 国产日韩在线免费| 有码中文亚洲精品| 伊人久久精品视频| 日韩精品在线视频观看| 欧美重口另类videos人妖| 国产色婷婷国产综合在线理论片a| 97免费中文视频在线观看| 亚洲国产欧美一区二区三区同亚洲| 成人www视频在线观看| 久久久久女教师免费一区| 欧美精品videossex性护士| 久久精品2019中文字幕|