今天同事(妹子)遇到一個 Zepto
的事件委託的問題來問我,我當時也懵了,後來解決了。問題仍是比較坑的,拿出來分享一下。先看看是什麼問題:git
頁面1github
爲何?!爲何事件委託在 .a
上但是卻也觸發了 .b
上的委託。看着妹子求知的眼神,我胸中一陣氣短。猜測着是 .a
委託事件最後換了 class
,DOM馬上更改了,就在 .a
事件後觸發了 .b
。因此我馬上讓她這樣改一下就能夠延緩DOM更改:this
$doc.on('click','.a',function(){ alert('a事件') var $this = $(this) ; setTimeout(function(){ $this.removeClass('a') .addClass('b') },30) })
而後就正常了 頁面2。spa
雖然妹子對我一陣讚許,但是我內心仍是隱隱不安,回來經過諮詢大牛和看源碼知道了這是什麼緣由。code
先看看這個頁面 頁面3blog
查看源碼咱們能夠看到,頁面3 和 頁面1 幾乎如出一轍,就是在 .a
和 .b
的事件委託順序不同:隊列
那爲何 頁面3 就能夠正常呢?就是由於 Zepto 的事件委託和咱們想象中的事件委託是不同的。事件
Zepto
的事件委託是:rem
在代碼解析的時候,全部document的全部
click
委託事件都依次放入一個隊列裏,click 的時候先看當前元素是否是.a
,符合就執行,而後查看是否是.b
,符合就執行。zepto
這樣的話,就致使若是 .a
的事件在前面,會先執行 .a
事件,而後 class
更改爲 b
,Zepto
再查看當前元素是否是 .b
,以此類推。
這就是 頁面1 出現BUG的緣由,而 頁面2 之因此也能解決這個問題是由於 class
變化實在延遲以後,click 事件當時沒有檢測到 .b
。
看看 Zepto 的事件部分是怎麼寫的。能夠看到是用$this.each
循環綁定在 $this
上的事件。對應在咱們的例子,就是 document
上綁定的事件都被塞進一個隊列中。
再看看 jQuery
的事件委託:
document上委託了2個 click 事件,click 後判斷是否當前符合條件(選擇符),而後把事件拿出來執行。
這是符合咱們通常的認知的,也是那個妹子那樣寫代碼的緣由。你不妨把頁面1的 Zepto
換成 jQuery
看看。
這是一個 Zepto
和 jQuery
不一樣的地方,之後要注意了。
個人博客,歡迎訂閱
微博粉絲太少,求粉