jQuery1 7系列四 事件

2021-08-26 18:59:16 字數 3745 閱讀 4141

宣告:寫部落格,是對自身知識的一種總結,也是一種分享,但由於作者本人水平有限,難免會有一些地方說得不對,還請大家友善  指出,或致電:[email protected]

關注:國內開源jquery-ui元件庫:operamasks-ui

jquery版本:v1.7.1

jquery1.7系列四: 事件

一. 有感而發

處理過前端指令碼事件的朋友都清楚,各瀏覽器在處理dom上的事件的不一致性讓人煩不勝煩。而為了提供一致的訪問介面,jquery作者提供了一套犀利的解決方案,這種思想是值得我們借鑑和學習的。

二.傳統事件處理蔽端

多說無益,我們直接從以下例子來看看瀏覽器間在事件處理方面的一些不一致性。

就上面這個非常簡單的例子,我們就可以看出幾個瀏覽器間事件處理會出現不一致的地方

1.    事件的繫結方式不同

2.    獲取event物件的方式不同

3.    event物件中的資料不完全相同

4.    對重複新增同一處理函式的處理方式不同,有人疊加有人忽略

還有一些例子沒有體現出來,比如不可以新增兩個處理事件,後新增的會覆蓋前面的;阻止事件冒泡的方式和阻止其預設行為;還有什麼,等你來挖掘。 

既然有如此多的不一致性,jquery作者當然想辦法要進行遮蔽了,而大師的處理方式將是本文章要**的內容。

三.jquery的事件處理方式

3.1  自己實現事件處理

事件繫結方式不同,這個解決不難,只要不同瀏覽器採用不同繫結方式,像第二部分的例子一樣就行了。但如何處理類似不可以新增多個處理函式這種侷限?我們自己來試著解決一下:

以上**雖然不是很多,但卻是jquery處理事件的乙個小縮影。我們 統一給dom節點註冊了乙個事件eventhandle,也就是說不管該dom觸發什麼型別的事件,一定會執行eventhandle,然後在 eventhandle中再呼叫dispatch進行分發,也就是根據事件型別在快取中查詢相應的處理器。這樣可以得到很多好處,最明顯的就是可以新增多 個處理器了,以後使用者再也不用怕相容性問題了,我們全部都隱藏在了內部實現中。當繫結完後,我們可以看下快取是怎樣的。

如果看懂了以上這個 event 的示例,那麼jquery關於事件的處理最核心的東西你已經知道了,接下來我們來看下jquery的做法。

3.2  jquery的事件處理

先來看個流程圖:

上圖是乙個處理流程圖,jquery分幾步來處理:

1.  給每個dom節點註冊乙個唯一的處理器(eventhandle)

2.  不管該dom觸發了什麼事件,都會執行eventhandle, 然後eventhandle呼叫dispatch進行事件的真正處理

3.  dispatch進行事件的修正,用jquery自定義的事件型別來包裝原生的event物件,這樣提供統一的訪問介面,如event.target在任何瀏覽器下表示觸發事件的源dom節點。

4.  在jquery公用快取中獲取該dom節點的處理器資料,由於委託機制的存在(稍後再講),所以先獲取此節點的委託處理器列表。

5.  把此節點的委託處理器列表與本節點本身的處理器列表進行合併,形成最終的處理器列表。

6.  執行最終的處理器列表,並即時處理取消冒泡和阻止瀏覽器預設行為。

看到這裡,發現大體思想還是比較簡單的吧,那我們再來深入一些細節,首先看看當繫結事件後快取的儲存情況怎樣?

html**

繫結後快取熱圖:

通過此圖我們可以看到這跟我們自己實現的快取方式是非常類似的,只是多了一些額外的東西,比如命名空間(稍後會講),事件委託。

另外提乙個,因為乙個事件型別可以有多個處理器函式,預設情況下,當你取消了冒泡行為時(event.stoppropagation),這多個處理器還 是會全部執行的,如果你想取消冒泡同時當前dom節點未執行的處理器函式也不執行了,則可以呼叫event. stopimmediatepropagation。

3.3   jquery事件委託 (delegate)

首先,我們通過乙個例子來看下什麼是事件的委託。

委託是種很方便的東西,說得白一點,就是孩子節點的事件處理器放在父節點的事件處理器列表中,讓父節點統一來進行觸發。如果沒有這種機制的話,那麼前面的例子就要單獨給每個tr新增事件了,浪費了不少的空間,而且有時還要寫多**。

就上面這個例子我們看下委託後的快取情況:

當我們雙擊了tr時,觸發tr雙擊事件,然後冒泡到table,table根據delegatecount的值進行檢查,因為 delegatecount=1,所以它會對table的事件處理器列表第乙個函式(個數由delegatecount決定)進行檢查,看它的 selector是否符合當前觸發事件的源dom節點,結果發現剛剛匹配,說明此函式也是要執行的,再與後邊剩餘(總數-delegatecount)的 函式列表進行合併,成為最終的函式處理器列表,這便是事件委託。

最後提一句,在事件的處理上,jquery1.7提供了兩個堪稱萬能的api,分別是on和off,至於怎麼用,就不多說了,文件一看就清楚了。

四. 命名空間

jquery事件還有乙個很新鮮的東西,那就是其獨有的命名空間了。但是此命名空間與我們普通想的卻是不太一樣的,來看看jquery的處理就知道怎麼回事了。

首先介紹一下這個命名空間。我們在繫結事件時可以這樣來繫結,$(「#btn」).bind(「click.www.jquery.com」, fn); 看到了嗎,在事件型別後邊可以加上」.www.jquery.com」這串東西,這整整一串就稱為命名空間。(不要自以為www是一級,jquery是一 級,com是一級),在這裡是沒有多級這種概念的。在儲存這個命名空間的時候,jquery會這樣做: 把www.jquery.com進行split,得到[「www」,」jquery」,」com」],然後進行sort,得到[「com」 , 「jquery」 , 「www」],然後再進行join得到com.jquery.www,最後儲存在快取當中。而當我們利用trigger想觸發某個事件時,比如我們執 行$(「#btn」).trigger(「click」),這時候jquery是這樣處理的:「click」並沒有命名空間,只有純粹的型別,所以觸發所 有型別為click的函式處理器(不管命名空間是什麼),但有乙個特例,也就是」!」號的使用,如果你剛剛寫的是 $(「#btn」).trigger(「click!」),那麼只會觸發型別為click,並且命名空間為空的函式處理器。

另外一種就是我們觸發有命名空間的事件了,比如$(「#btn」).trigger(「click.jquery.com」),這時候又怎麼處理呢?

click.jquery.com 的命名空間為  jquery.com,split一下,變成[「jquery」,」com」],再sort一下,成[「com」 , 「jquery」],再join一下,成「com.jquery」,然後依次檢查click型別的處理器,看看它的命名空間是否匹 配」com.jquery」,此例的匹配是這樣的:/(^|\.)com\.(?:.*\.)?jquery(\.|$) /.test(「com.jquery.www」);左邊的//正則是動態產生出來的,而test()中的」 com.jquery.www」則是處理器中的命名空間,只要這個匹配成功了,那麼該處理器便會得到執行。顯然此例子是匹配成功的。關於這個正則就不多說 了,並不是很難看懂。

五.  後語

本文主要是對jquery事件實現方式的乙個解說,並展示了自己實現的乙個簡單版本的事件處理,希望可以幫助大家對jquery事件的實現有更好的了解。

jQuery1 7版本之後的on方法

之前就一直受這個問題的困擾,在jquery1.7版本之後新增了on方法,之前就了解過,其優越性高於 live bind delegate 等方法,在此之前專案中想用這個來測試結果發現,居然動態生成的標籤點選了沒反應,而live方法卻能 夠支援,於是乎到處查資料,問,結果找了好久在一篇文章中終於找到了...

JQuery四 JQuery事件常用方法

1.selector event handler 2.selector bind event data handler eventobject event可以設定多個事件,用空格隔開 data為json格式的字串,在方法中可以用eventobject.data.argname方式來使用。select...

jQuery學習筆記四(jquery事件註冊)

原生js註冊相同的事件之後,後面註冊的會覆蓋掉前面註冊的,而jquery事件,後面註冊的不會覆蓋前面註冊的,這增強了事件處理能力。jquery的隱式迭代 jquery中如果選擇器可以找到零個,乙個或多個元素找到多個元素 當找到的是多個元素的時候,得到的實際上是乙個元素的集合,執行設定操作的時候,會對...