jQuery事件的綁定和委託能夠用多種方法實現,on() 、 bind() 、 live() 、 delegate() ,還有one()。javascript
有時咱們可能會像下面這樣綁定一個事件:css
上面的事件綁定,咱們能夠經過多種方式去實現:java
1. on()web
與on()對應的是off(),用來移除事件綁定:數組
off():移除on()進行的綁定服務器
one():只綁定一次。閉包
2. bind()app
參數:ide
type: 含有一個或多個事件類型的字符串,由空格分隔多個事件。好比"click"或"submit",還能夠是自定義事件名。函數
data:做爲event.data屬性值傳遞給事件對象的額外數據對象
fn:綁定到每一個匹配元素的事件上面的處理函數
type:含有一個或多個事件類型的字符串,由空格分隔多個事件。好比"click"或"submit",還能夠是自定義事件名。
data:做爲event.data屬性值傳遞給事件對象的額外數據對象
false: 將第三個參數設置爲false會使默認的動做失效。
同時綁定多個事件類型:
同時綁定多個事件類型/處理程序:
你能夠在事件處理以前傳遞一些附加的數據。
經過返回false來取消默認的行爲並阻止事件起泡。
bind存在的問題
若是表格中要綁定單擊事件的有10列500行,那麼查找和遍歷5000個單元格會致使腳本執行速度明顯變慢,而保存5000個td元素和相應的事件處理程序也會佔用大量內存(相似於讓每一個人親自站在門口等快遞)。
在前面這個例子的基礎上,若是咱們想實現一個簡單的相冊應用,每頁只顯示50張照片的縮略圖(50個單元格),用戶點擊「第x頁」(或「下一頁」)連接能夠經過Ajax從服務器動態加載另外50張照片。在這種狀況下,彷佛使用.bind()方法爲50個單元格綁定事件又能夠接受了。
事實卻否則。使用.bind()方法只會給第一頁中的50個單元格綁定單擊事件,動態加載的後續頁面中的單元格都不會有這個單擊事件。換句話說,.bind()只能給調用它的時候已經存在的元素綁定事件,不能給將來新增的元素綁定事件(相似於新來的員工收不到快遞)。
事件委託能夠解決上述兩個問題。具體到代碼上,只要用jQuery 1.3新增的.live()方法代替.bind()方法便可:
這裏的.live()方法會把click事件綁定到$(document)對象(但這一點從代碼中體現不出來,這也是.live()方法飽受詬病的一個重要緣由,稍後再詳細討論),並且只須要給$(document)綁定一次(不是50次,更不是5000次),而後就可以處理後續動態加載的照片單元格的單擊事件。在接收到任何事件時,$(document)對象都會檢查事件類型和事件目標,若是是click事件且事件目標是td,那麼就執行委託給它的處理程序。
unbind():移除bind進行的綁定。
3. live()
到目前爲止,一切彷佛很完美。惋惜,事實並不是如此。由於.live()方法並不完美,它有以下幾個主要缺點:
爲了不生成沒必要要的jQuery對象,可使用一種叫作「早委託」的hack,即在$(document).ready()方法外部調用.live():
在此,(function($){...})(jQuery)是一個「當即執行的匿名函數」,構成了一個閉包,能夠防止命名衝突。在匿名函數內部,$參數引用jQuery對象。這個匿名函數不會等到DOM就緒就會執行。注意,使用這個hack時,腳本必須是在頁面的head元素中連接和(或)執行的。之因此選擇這個時機,由於這時候恰好document元素可用,而整個DOM還遠未生成;若是把腳本放在結束的body標籤前面,就沒有意義了,由於那時候DOM已經徹底可用了。
爲了不事件冒泡形成的性能損失,jQuery從1.4開始支持在使用.live()方法時配合使用一個上下文參數:
這樣,「受託方」就從默認的$(document)變成了$("#info_table")[0],節省了冒泡的旅程。不過,與.live()共同使用的上下文參數必須是一個單獨的DOM元素,因此這裏指定上下文對象時使用的是$("#info_table")[0],即便用數組的索引操做符來取得的一個DOM元素。
3. delegate()
如前所述,爲了突破單一.bind()方法的侷限性,實現事件委託,jQuery 1.3引入了.live()方法。後來,爲解決「事件傳播鏈」過長的問題,jQuery 1.4又支持爲.live()方法指定上下文對象。而爲了解決無謂生成元素集合的問題,jQuery 1.4.2乾脆直接引入了一個新方法.delegate()。
使用.delegate(),前面的例子能夠這樣寫:
使用.delegate()有以下優勢(或者說解決了.live()方法的以下問題):
可見,.delegate()方法是一個相對完美的解決方案。但在DOM結構簡單的狀況下,也可使用.live()。
提示:使用事件委託時,若是註冊到目標元素上的其餘事件處理程序使用.stopPropagation()阻止了事件傳播,那麼事件委託就會失效。
undelegate():移除delegate的綁定