javascript事件机制研究

1. js事件模型

当我们点击页面上的一个元素时,浏览器是如何捕获并处理事件的。针对这个,js中有一个事件流的概念。当一个事件发生时会产生一个事件流,可通过event.eventPhase来获取当前处于哪个阶段。event.eventPhase的值与事件流阶段的对应关系如下:

      

描述
0当前没有事件被处理
1捕获阶段:从window开始,从上至下传播,直到到达目标的父元素。
2目标阶段:事件已到达目标target
3冒泡阶段:事件从目标target的父元素开始,从下到上传播,最终到达window。

      针对这几个阶段,提供了相关demo进行演示:点击进入


特别说明:ie低版本只支持冒泡


2. e.target与e.currentTarget的区别

属性描述
e.target触发事件的目标元素,即你点击了一个按钮,此时target就是那个按钮
e.currentTarget事件流当前所处阶段到达的元素。

这两个的区别demo演示,同上。


3. preventDefault与stopPropagation

  preventDefault:阻止元素针对所触发事件的默认行为;
      stopPropagation:阻止事件冒泡;

4. 什么是dispatchEvent

  手动触发事件。demo    参考资料


5. 事件代理的实现

类似于jquery的事件代理,原理就是利用事件流的冒泡阶段:把事件绑定在祖先元素A上,然后在事件处理器中,从e.target开始寻找,直至A结束(不包括A),看期间有没有某个元素是待监听的元素,如果是,则触发相应的处理事件。


6. 事件代理的问题<li><span></span></li>如果同时给span与li绑定事件该如何阻止冒泡???

这个的话,在上述第5条的例子中,我就已经给出了演示,调用e.stopPropagation()阻止冒泡就可以了。比如给span的处理事件中调用e.stopPropagation()

7. tap事件是如何实现的

tap,只指在移动设备,我们触发的一个“点击”事件。虽然有touchend和click,但直接监听这2个事件都有问题:

touchend:触摸动作结束,但是直接监听touchend会有一个常见的问题。比如我们给一个列表ul的li绑定touchend事件,但是此时用户在ul里向上滑动,想看剩下的列表项内容,会触发li的touchend事件,造成bug;
click:移动设备为了判断用户是单击,还是双击,还是其他动作。touchend后到触发click会有一个300ms的延时,这样子会造成页面反应迟钝。

tap事件,就是为了解决300ms延时。用户要绑定一个元素的点击事件,可以使用如Zepto里面的tap事件。

tap事件实现:
1. touchstart时,通过e.touches获取当前的触摸点,并记录起始坐标点pageX、pageY、 目标元素target及其他相关信息
2. touchmove时,记录触摸点移动的新坐标pageX、pageY,并和在touchstart里记录的起始坐标点算移动差值deltaX、deltaY;
3. touchend时,结合之前记录的各种数据,判断用户的操作手势swipe,tap,singleTap,doubleTap,来触发相应事件。不过值得说明的是,tap包含singleTap和doubleTap,其中singleTap会比tap有250ms的延时。

zepto的touch.js源码

8. tap会产生什么问题 

zepto的tap事件,产生一个很明显的问题就是“点透”

“点透”现象具体如下:




这个明显是个bug

分析:body是包含“蓝色块”的(即在DOM树上)在它冒泡到body之前,用户手的接触屏幕和离开屏幕是会先触发click事件的,(根据click事件的规则,只有在被触发时,当前有click事件的元素显示,且在面朝用户的最前端时,才触发click事件)由于click延迟,此时上面的“红色块”已经隐藏,满足下面的“蓝色块”的click事件的触发条件,于是click事件就被触发了,即“点透”了。

代码原因:其实就是因为zepto.touch.js,给body绑定touchend的时候,没有阻止默认事件。调用e.preventDefault()则可以阻止默认的click

document.body.addEventListener('touchend',function(e){
                e.preventDefault();
            });

这样子,点击红色块,不会触发蓝色块的click事件了。不过这个不是最好的方案,因为这样就阻止了页面上元素监听click事件了。

9. zepto的touch库做了什么?

给body绑定touchstart,touchmove,touchend事件,根据e.touches来获取触摸点,然后判断用户手势。具体说明请参见 第7点 

10. fastclick解决了什么问题


解决了click事件的300ms延时,也解决了zepto tap的点透。

请先查看fastclick官方说明

fastclick的实现方式和zepto.touch.js大同小异,但是有几点很重要的区分:

1. 可以任意指定需要绑定fastclick的元素,不会默认绑定在body上;

2. 在待绑定的元素上,监听touchend,阻止默认事件(即阻止了浏览器默认的click),手动触发目标元素的click事件(dispatchEvent)

11. 实现一个滑动touch库

简单实现一个在移动设备下,监听swipe手势的touch库,并识别up,down,left,right四个方向。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值