本章將把重點放在於對於事件的委託機制,以及jquery的事件綁定方法作一些解析。本章並無什麼比較難懂的地方,也尚未深刻到jQuery的事件系統內部。前端
上一章講了前端事件系統以及簡單地對各個瀏覽器進行兼容的方法。對於要求不高的頁面來講,以前的簡單事件註冊,就能夠很好的勝任各類各樣的工做了。可是,試想一種狀況。假若一個頁面有着極大量的事件綁定的需求,那麼咱們以前的事件系統,就不得不一個個的去綁定事件。這樣對性能來講,確定是一種災難,同時,動態增長的節點沒法完成綁定的工做。所以,咱們須要引入事件委託這一機制。jquery
咱們知道dom的事件處理,分爲捕獲階段,目標階段,以及冒泡階段三個部分。那麼簡單地講一下這三個階段吧,當咱們點擊了一個a標籤的時候,整個事件的流程大體是下面的階段api
首先事件從dom樹向下傳送,逐個訪問目標節點的祖先節點,同時將會對該事件的捕獲事件監聽器來進行檢測,並執行,直到訪問到目標節點,這一階段就是咱們說的捕獲階段;到達目標節點(即a標籤)後,就會執行該事件監聽器,這一階段也就是目標節點;最後事件將會從目標節點開始,從dom樹往上傳送,再依次訪問目標節點的祖先節點,而且執行對應的非捕獲事件的事件監聽器,而且執行瀏覽器
既然有了冒泡和捕獲的概念,那麼事件委託的原理也很好理解了。事件委託利用了事件能夠傳播的這一特性,並不使用事件自己對於事件來進行處理,而是將對事件的處理任務交予了其祖先節點來進行處理。dom
這樣作,減小了對於頁面上的dom操做。好比你對ul下的li綁定事件,經過事件委託,你只須要對於ul綁定一次事件,而後使用事件傳播的這一特性,li的事件來進行工做,這樣,極大地減小了綁定量,並且即便是動態增長的li節點,也一樣是能夠去執行該事件的。函數
那麼終於來到了jQuery的部分。從這裏開始也將對jQuery的事件部分,盡我的所能來作一個解析,以後出現jQuery的源碼的版本爲2.1.4,解析過程當中有不對的地方,歡迎打臉。性能
jQuery的事件綁定,有如下幾種方法:學習
那麼咱們對上面幾種方法來一一分析(本章暫不會對做爲核心的on的源碼來進行分析)this
直接用事件名進行事件綁定翻譯
便是直接採用相似.click(),.blur()的方式進行綁定
那麼jQuery中是如何作到的呢
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 binding jQuery.fn[ name ] = function( data, fn ) { return arguments.length > 0 ? this.on( name, null, data, fn ) : this.trigger( name ); }; });
jQuery的實現很簡單,將事件直接經過each方法加入jQuery.fn上,而後在內部根據參數的不一樣直接對於jQuery的on或者trigger方法進行調用。
bind方法
bind方法用於爲一個元素綁定一個事件處理程序
先來看看jQuery中的實現吧
bind: function( types, data, fn ) { return this.on( types, null, data, fn ); }
live方法
live方法拿到前面來講。這是jQuery如今已經不支持的方法。對於1.4.3以上的版本,推薦採delgate方法來,而對於1.7以上的版本,則推薦採用on方法來進行替代。具體採用live方法有什麼弊端,jQuery的文檔之中已經闡述的很是明白了,至於爲何會出現這個問題,本着刻苦求知的精神……我還並無去看,附上翻譯後的文檔吧
由於更高版本的jQuery提供了更好的方法,沒有.live()方法的缺點,因此.live()方法再也不推薦使用。特別是,使用.live()出現的如下問題:
- 在調用 .live() 方法以前,jQuery 會先獲取與指定的選擇器匹配的元素,這一點對於大型文檔來講是很花費時間的。
- 不支持鏈式寫法。例如,$("a").find(".offsite, .external").live( ... ); 這樣的寫法是不合法的,並不能像期待的那樣起做用。
- 因爲全部的 .live() 事件被添加到 document 元素上,因此在事件被處理以前,可能會經過最長最慢的那條路徑以後才能被觸發。
- 在移動 iOS (iPhone, iPad 和 iPod Touch) 上,對於大多數元素而言,click 事件不會冒泡到文檔 body 上,而且若是不知足以下狀況之一,就不能和 .live() 方法一塊兒使用:
- 使用原生的可被點擊的元素,例如, a 或 button,由於這兩個元素能夠冒泡到 document。
- 在 document.body 內的元素使用 .on() 或 .delegate() 進行綁定,由於移動 iOS 只有在 body 內才能進行冒泡。
- 須要 click 冒泡到元素上才能應用的 CSS 樣式 cursor:pointer (或者是父元素包含 document.documentElement)。可是依需注意的是,這樣會禁止元素上的複製/粘貼功能,而且當點擊元素時,會致使該元素被高亮顯示。
- 在事件處理中調用 event.stopPropagation() 來阻止事件處理被添加到 document 以後的節點中,是效率很低的。由於事件已經被傳播到 document 上。
- .live() 方法與其它事件方法的相互影響是會使人感到驚訝的。例如,$(document).unbind("click") 會移除全部經過 .live() 添加的 click 事件!
delegate方法
delegate方法也就是咱們以前所提到的事件委託了。由於基於live以前的不少問題,jQuery在live以後的版本中增長了delgate方法(現在已經被on所取代)
來看看如今的delegate是如何實現的吧
delegate: function( selector, types, data, fn ) { return this.on( types, selector, data, fn ); }
one方法
爲元素添加事件。而且在元素上的事件只能夠執行一次
具體實現
one: function( types, selector, data, fn ) { return this.on( types, selector, data, fn, 1 ); }
on方法
on方法在這裏不打算對源碼進行閱讀,由於能夠看到,上面的全部方法都是對於on方法的調用。所以jQuery的事件系統,核心就在於on方法了。所以jQuery的on方法將在後面進行分析,而這裏,只是對於on接口自己的一些說明。
on方法提供了綁定事件全部的功能。其API是這樣的
.on( events [, selector ] [, data ], handler(eventObject) )
其實最後還有一個one參數,假若傳入了1,那麼這個事件也就只執行一次,而實現的原理其實也就是使用off來解綁事件進行的操做了。
而後來看下別的參數分別是作些什麼的吧
events: 類型: String 一個或多個空格分隔的事件類型和可選的命名空間,或僅僅是命名空間,好比"click", "keydown.myPlugin", 或者 ".myPlugin"。 selector: 類型: String 一個選擇器字符串,用於過濾出被選中的元素中能觸發事件的後代元素。若是選擇器是 null 或者忽略了該選擇器,那麼被選中的元素老是能觸發事件。 data: 類型: Anything 當一個事件被觸發時,要傳遞給事件處理函數的event.data。 handler(eventObject) 類型: Function() 事件被觸發時,執行的函數。若該函數只是要執行return false的話,那麼該參數位置能夠直接簡寫成 false。
所以再來對於前面五種方法來進行統一的分析。
直接用事件名進行事件綁定的方法與bind的方法,直接對於selector參數賦值爲了null,所以,對於採用這兩種方法進行的事件綁定,其實自己是沒有使用事件委託的,便是說並無冒泡的過程,所以,採用這種方法的綁定對性能會有必定的損耗。
而delegate方法,傳入了selector參數,所以,至關於也就是直接用on來實現的事件委託。
one方法以前也講了,因此再也不多說。
總結一下這章所講的內容吧。本章對於事件綁定的幾種方法(除on外),都進行了簡單地講解。與其說是對於jQuery源碼的分析,倒不如說其實就是個簡單地,對於jQuery使用的建議吧。jQuery綁定的核心仍是落在on方法上,同時,jQuery的事件系統的思想能夠說是極爲經典的。在下一章,咱們將對jQuery的事件系統進行更深刻一些的分析(在我捉急的水平範圍以內)。第三章估計要難產了,我必定會努力作完這個系列的,也算是對我的前端學習的一點鞭策吧。