click点透

什么是click点透?

核心代码:
<div class="content">
<div id="underLayer">
<a href="www.baidu.com">链接</a>
<input type="text" class="text1" >
<input type="select" class="select">
<input type="radio" class="select">
<input type="checkbox" class="select">
<button class="btn" id="openPopup">弹出</button>
</div>
<div id="popupLayer">
<div class="layer-title">弹出层</div>
<div class="layer-action">
<button class="btn" id="closePopup">关闭</button>
</div>
</div>
</div>

<script type="text/javascript">

  var oPop =document.getElementById('popupLayer');
  var oUn = document.getElementById('underLayer');
  var oOpen = document.getElementById('openPopup');

  oPop.addEventListener('touchend', function(e){
      this.style.display='none';

     
  });

 oUn.addEventListener('click',
   function(){
      alert('1');
  } );

</script>

点击弹出层,touch事件首先被触发,弹出层和遮罩就被隐藏了。touchend后继续等待300ms发现没有其他行为了,则继续触发click,由于这时弹出层已经消失,所以当前click事件的target就在底层元素上,于是就alert内容。整个事件触发过程为 touchend -> click。
而由于click事件的滞后性(300ms),在这300ms内上层元素隐藏或消失了,下层同样位置的DOM元素触发了click事件(如果是input框则会触发focus事件,如果是<a>链接则会进行页面跳转,或是 select / radio / checkbox都会被触发),看起来就像点击的target“穿透”到下层去了。这就是点透现象

解决方法:
a、阻止默认事件 e.preventDefault() 给touchend事

件加上 e.preventDefault()
oPop.addEventListener('touchend', function(e){
this.style.display='none';
e.preventDefault();
});

b、利用css3属性 pointer-events
取值auto|none
当取值为auto 时,效果和没有定义 pointer-events 属性相同,鼠标不会穿透当前层。
当取值为none 时,元素不再是鼠标事件的目标,鼠标不再监听当前层而去监听下面的层中的元素。但是如果它的子元素设置了pointer-events为其它值,比如auto,鼠标还是会监听这个子元素的。
详细代码:
oPop.addEventListener('touchend', function(e){
this.style.display='none';
oUn.style.pointerEvents='none';

    setTimeout(function(){
        oUn.style.pointerEvents='auto';
    }, 400);
  });

c. 遮挡
由于 click 事件的滞后性,在这段时间内原来点击的元素消失了,于是便“穿透”了。因此我们顺着这个思路就想到,可以给元素的消失做一个fade效果,类似jQuery里的fadeOut,并设置动画duration大于300ms,这样当延迟的 click 触发时,就不会“穿透”到下方的元素了。
同样的道理,不用延时动画,我们还可以在触摸位置放一个透明的元素,这样当上层元素消失而延迟的click来到时,它点击到的是那个透明的元素,也不会“穿透”到底下。在一定的timeout后再将生成的透明元素隐藏。代码如下:

oPop.addEventListener('touchend', function(e){
oBg.style.display ='block';
this.style.display='none';

  // 解决方法三
  setTimeout(function(){
       oBg.style.display='none'
    }, 400);

     
  });

参考彻底理解和解决移动WEB开发中CLICK点透问题

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容