Zepto事件委託的小坑

risker發表於2015-12-14

問題

今天同事(妹子)遇到一個 Zepto 的事件委託的問題來問我,我當時也懵了,後來解決了。問題還是比較坑的,拿出來分享一下。先看看是什麼問題:

頁面1

自己解決

為什麼?!為什麼事件委託在 .a 上可是卻也觸發了 .b 上的委託。看著妹子求知的眼神,我胸中一陣氣短。猜想著是 .a 委託事件最後換了 class,DOM立刻更改了,就在 .a 事件後觸發了 .b。所以我立刻讓她這樣改一下就可以延緩DOM更改:

然後就正常了 頁面2

刨根問底

雖然妹子對我一陣讚許,可是我心裡還是隱隱不安,回來通過諮詢大牛和看原始碼知道了這是什麼原因。

先看看這個頁面 頁面3

檢視原始碼我們可以看到,頁面3頁面1 幾乎一模一樣,就是在 .a.b 的事件委託順序不一樣:

頁面1

頁面3

那為什麼 頁面3 就可以正常呢?就是因為 Zepto 的事件委託和我們想象中的事件委託是不一樣的。

Zepto 的事件委託是:

在程式碼解析的時候,所有document的所有 click 委託事件都依次放入一個佇列裡,click 的時候先看當前元素是不是.a,符合就執行,然後檢視是不是.b,符合就執行。

這樣的話,就導致如果 .a 的事件在前面,會先執行 .a 事件,然後 class 更改成 bZepto再檢視當前元素是不是 .b,以此類推。

這就是 頁面1 出現BUG的原因,而 頁面2 之所以也能解決這個問題是因為 class 變化實在延遲之後,click 事件當時沒有檢測到 .b

看看 Zepto 的事件部分是怎麼寫的。可以看到是用$this.each 迴圈繫結在 $this 上的事件。對應在我們的例子,就是 document 上繫結的事件都被塞進一個佇列中。

再看看 jQuery 的事件委託:

document上委託了2個 click 事件,click 後判斷是否當前符合條件(選擇符),然後把事件拿出來執行。

這是符合我們一般的認知的,也是那個妹子那樣寫程式碼的原因。你不妨把頁面1的 Zepto 換成 jQuery 看看。

這是一個 ZeptojQuery 不同的地方,以後要注意了。

>

我的部落格,歡迎訂閱

相關文章