Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Zepto事件委托的小坑 #14

Open
riskers opened this issue Nov 30, 2015 · 9 comments
Open

Zepto事件委托的小坑 #14

riskers opened this issue Nov 30, 2015 · 9 comments
Labels
FE web 前端

Comments

@riskers
Copy link
Owner

riskers commented Nov 30, 2015

问题

今天同事(妹子)遇到一个 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 的事件委托顺序不一样:

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


向我捐助 | 关于我 | 工作机会


@finas
Copy link

finas commented Dec 3, 2015

个人理解,委托是一个选择器和事件的map。selector=>[events]。zepto的委托是遍历selector立刻执行对应的events,当匹配到.a后执行events然后下一个匹配,同时匹配到了.b继续执行events。jQuery的委托是遍历selector如果匹配,push events到匹配元素的等待执行函数里。等待遍历完所有selectors再执行等该执行函数。不知道理解的是否有误。

@riskers
Copy link
Owner Author

riskers commented Dec 3, 2015

@finas 是的

Zepto 的实现就像排队,先排的先执行

jQuery 是把所有事件都一起执行的

@cssmagic
Copy link

cssmagic commented Dec 6, 2015

谢谢分享!

@riskers
Copy link
Owner Author

riskers commented Dec 6, 2015

@cssmagic 谢谢魔法哥 😄

@xbzhs
Copy link

xbzhs commented Aug 3, 2016

学习了

@codezyc
Copy link

codezyc commented Aug 14, 2016

@shiiiiiiji
Copy link

博客形式很赞!

@fatfish516
Copy link

感谢大佬分享

@ray-toby
Copy link

@riskers riskers added FE web 前端 and removed zepto labels Dec 17, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
FE web 前端
Projects
None yet
Development

No branches or pull requests

8 participants