一、什么是点透?html
举例说明:下图B元素是黄色方块,B元素中包含了C元素,C元素是一个a连接,自己自带click事件按,而后又一个半透明的粉色元素A遮盖在B元素上(看图中A元素是覆盖在B元素上的,否则B元素区域应该是正黄色,如今是橙黄色,证实B上面被A覆盖着);浏览器
代码以下:app
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"> <title>Title</title> <style> *{margin:0;padding:0;} #div1{width:300px;height:300px;background-color:rgba(255,0,0,.25);}/*红色半透明遮盖层*/ #div2{width:240px;height:240px;background-color:yellow;position:absolute;left:30px;top:30px;;z-index:-1;}/*黄色内容层B*/ #console{border:1px solid green;position:absolute;top:300px;width:100%;}/*绿色状态输出框*/ </style> </head> <body> <div id="div1"></div> <div id="div2"> <a href="www.baidu.com">www.baidu.com</a> </div> <div id="console"></div> <script> var div1=document.getElementById('div1'); var div2=document.getElementById('div2'); var con=document.getElementById('console'); function handle(e){ /*#div1点击的时候touchstart\touchend都会触发这个事件,而后经过e.type判断事件类型来区分是touchstart仍是touchend*/ var tar= e.target,eve= e.type; var ele=document.createElement('p'); ele.innerHTML='target:'+tar.id+'event:'+eve; con.appendChild(ele); if(tar.id==='div1'){ div1.style.display='none'; } } div1.addEventListener('touchend',handle); div1.addEventListener('touchstart',handle); </script> </body> </html>
上面代码点击图中除C区域之外的地方,固然是说A、B,都不会出现任何问题,结果以下:框架
target:div1 event:touchstart
target:div1 event:touchend
可是当你点击元素C的时候首先A元素会消失,而后页面会跳转到百度首页,按理来讲A元素遮盖住了元素B、C,可是这里A的touchstart事件却点透了A元素,触发了C元素上的click事件,这就是传说中的点透。spa
为了更清楚的看到这个过程,咱们在B元素上也绑定一个click事件,scala
div2.addEventListener('click',handle);
点击B区域,结果以下:code
target:div1 event:touchstart
target:div1 event:touchend
target:div2 event:click
可见先触发了A元素上的touchstart、touchend事件,以后又触发了B元素上的click事件,这也是点透现象的证实。htm
二、点透现象出现的场景blog
一、A、B两个元素上下Z轴重合,就是上下摞一块儿了;事件
二、上层的A点击后消失(这点很重要);
三、B自己有默认click事件(如a标签),或者B元素自己绑定了click事件;
四、在以上状况下,点击A、B重叠的部分,就会出现点透现象。
三、点透产生的缘由
click延迟,延迟,仍是延迟!!!
在移动端不适用click事件,而是用touch事件代替,就是由于click事件有着明显的延迟,具体touch和click的区别以下:
1、touchstart,在这个DOM(或冒泡到这个DOM)上手指触摸就能触发; 2、click,在这个DOM上手指触摸,且手指不曾在屏幕上移动(某些浏览器容许一个很是小的位移值),且在这个DOM上手指离开屏幕,且触摸和离开屏幕之间的时间间隔较短(某些浏览器不检测间隔时间,也会触发click)才能触发。
也就是说,事件的触发事件从早到晚为:touchstart早于touchend,早于click,亦即click的触发是有延迟的,这个时间大概是300ms。
因为咱们在touchstart阶段就隐藏了A元素,当click被触发时候,可以被点击的元素则是其下的B元素。
四、解决方案
一、对于B元素自己没有默认click事件的状况下(无a标签等),应统一使用touch事件,统一代码风格,而且因为click事件在移动端延迟要大不少,不利于用户体验,因此触摸事件应尽可能使用touch事件。
二、对于B元素自己存在默认click事件的状况,应即时取消A元素的默认点击事件,阻止click事件的产生,即给A元素绑定touchend事件,在事件中阻止默认行为:
$("#div1").on("touchend", function (event) { event.preventDefault(); });
三、针对遮盖层使用click事件,而不是touch事件,这是由于遮盖层的点击有小延迟也是没有关系的,反而会有疑似更好的用户体验。
五、现有解决方案框架(库)
一、众所周知,zepto的tap事件存在点透现象,可是最新版的zepto已经解决了这个问题,
二、在zepto修复问题以前,有fastclick、hammer等通用库可使用。
本文参考了http://www.cnblogs.com/zldream1106/p/3670988.html、http://www.cnblogs.com/wqhwe/p/5630557.html的文章。