click 事件的300毫秒的延后性质造成了, 点击了上层消失后,click 事件还没有触发到, 上层消失后,下面的documenr 被触发 click 事件;仿佛穿透;

在手机上,当我们手触碰屏幕时,要过300ms左右才会触发mousedown事件,所以click事件在手机上看起来就像慢半拍一样。

PC网页上的大部分操作都是用鼠标的,即响应的是鼠标事件,包括mousedownmouseupmousemoveclick事件。一次点击行为,事件的触发过程为:mousedown -> mouseup -> click 三步。

手机上没有鼠标,所以就用触摸事件去实现类似的功能。touch事件包含touchstarttouchmovetouchend,注意手机上并没有tap事件。手指触发触摸事件的过程为:touchstart -> touchmove -> touchend

用过Zepto或KISSY等移动端js库的人肯定对tap事件不陌生,我们做PC页面时绑定click,相应地手机页面就绑定tap。但原生的touch事件本身是没有tap的,js库里提供的tap事件都是模拟出来的。

我们在上面看到,手机上响应 click 事件会有300ms的延迟,那么这300ms到底是干嘛了?浏览器在 touchend 后会等待约300ms,原因是判断用户是否有双击(double tap)行为。如果没有 tap 行为,则触发 click 事件,而双击过程中就不适合触发 click 事件了。由此可以看出 click 事件触发代表一轮触摸事件的结束。

既然说tap事件是模拟出来的,我们可以看下Zepto对 singleTap 事件的处理。见源码 136-143 行,可以看出在 touchend 响应 250ms 无操作后,则触发singleTap。

touch事件中可以获取以下参数

参数

含义

touches

屏幕中每根手指信息列表

targetTouches

和touches类似,把同一节点的手指信息过滤掉

changedTouches

响应当前事件的每根手指的信息列表

解决:

1. 触摸结束时 touchend 事件触发时,preventDefault()。看上去好像没有什么问题,但是,很遗憾的是不是所有的浏览器都支持。

 2. 禁止页面缩放 通过设置meta标签,可以禁止页面缩放,部分浏览器不再需要等待 300ms,导致点击穿透。点击事件仍然会触发,但相对较快,所以 click 事件从某种意义上来说可以取代点击事件, 而代价是牺牲少数用户(click 事件触发仍然较慢)的体验。


IE 10可以用 CSS 取消点击穿透的延迟:


html { -ms-touch-action: manipulation; touch-action: manipulation; }


IE 11+ 可以用 touch-action: manipulation; 属性来阻止元素的双击缩放

 3. CSS3 的方法 虽然主要讲的是事件,但是有必要介绍一个 CSS3 的属性 —— pointer-events。


pointer-events: auto | none | visiblePainted | visibleFill | visibleStroke | visible | painted | fill | stroke | all | inherit;


pointer-events 属性有很多值,有用的主要是 auto 和 none,其他属性为 SVG 服务。

查看浏览器支持情况 可见移动端开发还是可以用的。

属性

含义

auto

默认值,鼠标或触屏事件不会穿透当前层

none

元素不再是target,监听的元素变成了下层的元素(如果子元素设置成 auto,点击子元素会继续监听事件)

 

$('#closePopup').on('tap', function(e){
    $('#popupLayer').hide();
    $('#bgMask').hide();

    $('#underLayer').css('pointer-events', 'none');

    setTimeout(function(){
        $('#underLayer').css('pointer-events', 'auto');
    }, 400);
});

 

4.延长消失事件 可以利用jquery的fadeout,设置事件大于300ms。