WAP端 穿透问题和解决方法

1. 穿透问题可这么理解, 共有2种问题:
  问题1: 有A 和 B 两个弹层,B 弹层盖在A 弹层上面,B 弹层绑定 touchend 事件,当用户点击B 的时候 B隐藏,由于touchend 事件触发的太快了,导致用户点击到弹层下面的具有click 属性的元素的东东。(包括 A 标签<a href='#'></a> 或 input 框 或 绑定了 click 事件的元素)

  奇怪的是, 若给链接A 绑定了touchend 并且e.preventDefault() 也是不起作用。请看下面的例子,也就是它根本没有执行 touchend 事件,但是却执行了A 元素的 href 跳转链接。

<a href='https://www.baidu.com/'></a>

<script type='text/javascript'>
  // B 是在 a 链接上面的弹层
  B.on('touchend', function(){
    B.hide();
  });

  // 大部分浏览器都不会执行 console.log,但是 ios 8.4 safari 不跳转,因为它本来就没有穿透问题。
  $('a').on('touchend', function(e){ 
    console.log('touchend');
    e.preventDefault(); 
  });
</script>

浏览器表现 :
  ios 8.4 safari 页面不跳转
  ios 8.4 UC 10.6.5.627 跳转
  ios 7.0 safari 跳转
  ios 7.0 UC 10.6.5.627 跳转
  SAMSUNG GT-19308 4.3 UC 10.6.5.627 跳转
  SAMSUNG GT-19308 4.3 跳转。 若直接点击链接 a,竟然会跳转,e.preventDefault() 竟然没作用,只有这个浏览器会。想点击 a 链接不跳转,只能绑定 click 事件并且 e.preventDefault();

 

  问题2:有A 和 B两个元素,B 元素盖在A 元素上面,B元素默认隐藏。A元素绑定事件让B 元素显示出来,B元素点击自己隐藏。出现的现象是: 点击A元素 B元素显示不出,因为触发了B元素里的代码。

A.on('touchend', function(){
  B.show();
});

// 就算B 元素用 touchend 绑定, 有的手机也还是会触发 B.hide();
B.on('click', function(){
  B.hide();
});

 

解决穿透问题1: 

各个浏览器的表现
  iOS 8.4 safari用touchend 关闭 不会穿透下面绑定的 click 事件, 所以什么事都不用做,很完美。
  iOS 8.4 和 iOS 7.0 UC浏览器弹窗关闭用 setTimeout(function(){ 弹层.hide() }, 0); 可以解决弹层穿透。
  另外备注下: UC 浏览器做过优化,下面的代码 click 事件比 touchend的触发的快。

$('.m').on('touchend', function(){
    setTimeout(function(){
        console.log('touchend');
    }, 0);
});

$('.m').click(function(){
    console.log('click');
});

iOS 7.0 safari的不行,只能用 e.preventDefault() 解决 或者设置 setTimeout(.. 360),而 e.preventDefault() 也支持 ios8.4 safari和UC版本的。

Android 的手机 4.1.1 JRO03L MIUI-JLB14.0, e.preventDefault();不能解决,但是 setTiemout 只要在 >=300 就可以解决了。

所以最终的解决办法:

  由于 iOS 7.0上 setTimeout 360毫秒 的时间太长了,所以直接给 B弹层绑定 e.preventDefault();

B.on('touchend', function(e){
    e.preventDefault();
    B.hide();
});

   Android上解决方式通过属性 pointer-events: none; 让整个页面都不能有点击的属性, 301秒以后恢复属性值。

B.on('touchend', function(){
    $('html').css({
        pointer-events: 'none'
    });
    setTimeout(function(){
        $('html').css({
            pointer-events: 'auto'
        });
    }, 301);

    B.hide();
});

 

解决穿透问题2:

  解决方式比较简单, A 里面用 e.preventDefault(), 注意A也不能绑定tap; B 绑定 touchend

A.on('touchend', function(e){
    e.preventDefault();
    B.show();
});


B.on('touchend', function(){
    B.hide();
});

 

2. 当给一个元素绑定 touchend 事件和click事件, touchend事件让元素关闭,那么都不会触发到 click 事件,浏览器如下。
  SAMSUNG GT-19308 4.3 原生浏览器 和 UC浏览器 10.6.5.627
  IOS7.0 safari 和 UC浏览器 10.6.5.627
  IOS8.4 safari 和 UC浏览器 10.6.5.627

 

3. fastClick

通过绑定 body touchend,然后通过逻辑找到 e.target 元素,满足条件下执行 e.preventDefault(); 阻止了 click事件,然后让 initMouseEvent 和 dispatchEvent 来触发。

问题1的是否解决 的浏览器兼容如下:

SAMSUNG GT-19308 4.3 和 ios8.4
  原生浏览器和safari 可以
  UC浏览器都 可以

ios7.0 safri 和 UC浏览器 都不可以

 

4. 注意:若给 html 根元素绑定了
$('html').on('touchend', function(){ e.preventDefault(); })
则页面里所有的元素 click 绑定的事件都触发不了, input 都不能点击输入了。

posted @ 2016-06-07 16:37  zhengming  阅读(303)  评论(0编辑  收藏  举报