问题
今天同事(妹子)遇到一个 Zepto
的事件委托的问题来问我,我当时也懵了,后来解决了。问题还是比较坑的,拿出来分享一下。先看看是什么问题:
自己解决
为什么?!为什么事件委托在 .a
上可是却也触发了 .b
上的委托。看着妹子求知的眼神,我胸中一阵气短。猜想着是 .a
委托事件最后换了 class
,DOM立刻更改了,就在 .a
事件后触发了 .b
。所以我立刻让她这样改一下就可以延缓DOM更改:
1 2 3 4 5 6 7 8 9 |
$doc.on('click','.a',function(){ alert('a事件') var $this = $(this) ; setTimeout(function(){ $this.removeClass('a') .addClass('b') },30) }) |
然后就正常了 页面2。
刨根问底
虽然妹子对我一阵赞许,可是我心里还是隐隐不安,回来通过咨询大牛和看源码知道了这是什么原因。
先看看这个页面 页面3
查看源码我们可以看到,页面3 和 页面1 几乎一模一样,就是在 .a
和 .b
的事件委托顺序不一样:
那为什么 页面3 就可以正常呢?就是因为 Zepto 的事件委托和我们想象中的事件委托是不一样的。
Zepto
的事件委托是:
在代码解析的时候,所有document的所有
click
委托事件都依次放入一个队列里,click 的时候先看当前元素是不是.a
,符合就执行,然后查看是不是.b
,符合就执行。
这样的话,就导致如果 .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
不同的地方,以后要注意了。
>
我的博客,欢迎订阅