4

问题

今天同事(妹子)遇到一个 Zepto 的事件委托的问题来问我,我当时也懵了,后来解决了。问题还是比较坑的,拿出来分享一下。先看看是什么问题:

页面1

自己解决

为什么?!为什么事件委托在 .a 上可是却也触发了 .b 上的委托。看着妹子求知的眼神,我胸中一阵气短。猜想着是 .a 委托事件最后换了 class,DOM立刻更改了,就在 .a 事件后触发了 .b。所以我立刻让她这样改一下就可以延缓DOM更改:

$doc.on('click','.a',function(){
    alert('a事件')
    var $this = $(this) ;
    setTimeout(function(){
        $this.removeClass('a')
        .addClass('b')    
    },30)
})

然后就正常了 页面2

刨根问底

虽然妹子对我一阵赞许,可是我心里还是隐隐不安,回来通过咨询大牛和看源码知道了这是什么原因。

先看看这个页面 页面3

查看源码我们可以看到,页面3页面1 几乎一模一样,就是在 .a.b 的事件委托顺序不一样:

89602268.jpg

29574817.jpg

那为什么 页面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 不同的地方,以后要注意了。

我的博客,欢迎订阅

微博粉丝太少,求粉


一波不是一波
1.7k 声望91 粉丝

引用和评论

0 条评论