jQuery 2.0.3 源码分析 事件体系结构
那么jQuery事件處理機制能幫我們處理那些問題?
為了更深入的理解幕后的實現(xiàn),所以先整理整體的結(jié)構(gòu)思路,從1.7后就去除了live綁定,所以現(xiàn)在的整個事件的API
如圖:
?
jQuery的事件綁定有多個方法可以調(diào)用,以click事件來舉例:
- click方法
- bind方法
- delegate方法
- on方法
以上四種綁定都能達(dá)到同一樣的效果,但是各自又有什么區(qū)別,內(nèi)部又是如何實現(xiàn)?
?
源碼分析
?
click方式
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 ) {// Handle event bindingjQuery.fn[ name ] = function( data, fn ) {return arguments.length > 0 ?this.on( name, null, data, fn ) :this.trigger( name );};});源碼很簡單,合并15種事件統(tǒng)一增加到j(luò)Query.fn上
內(nèi)部調(diào)用this.on / this.trigger
?
bind方式
bind: function( types, data, fn ) {return this.on( types, null, data, fn ); }, unbind: function( types, fn ) {return this.off( types, null, fn ); },同樣調(diào)用的this.on/this.off
?
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 ); }同樣調(diào)用的this.on/this.off
?
one方式
one: function( types, selector, data, fn ) {return this.on( types, selector, data, fn, 1 ); },還是this.on
?
可見以上的接口只是修改了不同的傳遞參數(shù),最后都交給on實現(xiàn)的
?
實現(xiàn)最簡單的事件委托
給父元素綁定事件,子元素也能響應(yīng)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> <!-----------------------------測試代碼開始--------------------------------> <div id='p' style="width:500px;height: 500px;background:red"> <div id="test" style="width:50px;height: 50px;background:chartreuse">點擊</div> </div> <span id="preserve2b9f1efd3c03447e90ebbff63aeee026" class="wlWriterPreserve"><script> var p = document.getElementById('p'); p.onclick = function(e){ alert(e.target.id) } </script></span> <!-----------------------------測試結(jié)束--------------------------------------> </body> </html>
?
其實委托的原理都是一樣的,通過事件對象過濾出關(guān)聯(lián)目標(biāo)的hack,做相對應(yīng)的處理,那么JQuery是如何實現(xiàn)的呢?
?
jQuery事件的流程圖
在綁定階段與執(zhí)行階段
?
?
?
那么JQuery為了更好的對事件的支持內(nèi)部又做了哪些額外的優(yōu)化操作?
?
兼容性問題處理:
瀏覽器的事件兼容性是一個令人頭疼的問題。IE的event在是在全局的window下, 而mozilla的event是事件源參數(shù)傳入到回調(diào)函數(shù)中。還有很多的事件處理方式也一樣
JQuery提供了一個 event的兼容類方案
jQuery.event.fix 對游覽器的差異性進(jìn)行包裝處理
例如:
?
事件的存儲優(yōu)化:
jQuery并沒有將事件處理函數(shù)直接綁定到DOM元素上,而是通過$.data存儲在緩存$.cahce上,這里就是之前分析的貫穿整個體系的緩存系統(tǒng)了
聲明綁定的時候:
- 首先為DOM元素分配一個唯一ID,綁定的事件存儲在$.cahce[ 唯一ID ][ $.expand ][ 'events' ]上,而events是個鍵-值映射對象,鍵就是事件類型,對應(yīng)的值就是由事件處理函數(shù)組成的數(shù)組,最后在DOM元素上綁定(addEventListener/ attachEvent)一個事件處理函數(shù)eventHandle,這個過程由 jQuery.event.add 實現(xiàn)。
執(zhí)行綁定的時候:
- 當(dāng)事件觸發(fā)時eventHandle被執(zhí)行,eventHandle再去$.cache中尋找曾經(jīng)綁定的事件處理函數(shù)并執(zhí)行,這個過程由 jQuery.event. trigger 和 jQuery.event.handle實現(xiàn)。
- 事件的銷毀則由jQuery.event.remove 實現(xiàn),remove對緩存$.cahce中存儲的事件數(shù)組進(jìn)行銷毀,當(dāng)緩存中的事件全部銷毀時,調(diào)用removeEventListener/ detachEvent銷毀綁定在DOM元素上的事件處理函數(shù)eventHandle。
?
事件處理器:
jQuery.event.handlers
針對事件委托和原生事件(例如"click")綁定 區(qū)分對待
事件委托從隊列頭部推入,而普通事件綁定從尾部推入,通過記錄delegateCount來劃分,委托(delegate)綁定和普通綁定。
?
其余一些兼容事件的Hooks
fixHooks,keyHooks,mouseHooks
?
總的來說對于JQuery的事件綁定
在綁定的時候做了包裝處理
在執(zhí)行的時候有過濾器處理
?
下章就開始深入on內(nèi)部實現(xiàn)的分析了
總結(jié)
以上是生活随笔為你收集整理的jQuery 2.0.3 源码分析 事件体系结构的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MBProgressHUD
- 下一篇: 基于Django实现RBAC权限管理