记录前端开发学习与积累

移动页面点击击穿问题

问题

在移动端,click 事件有 300ms 的延迟,当 touchend 事件把上层元素隐藏之后,隔了300ms,浏览器触发了 click 事件,但是此时上层元素不见了,所以该事件被派发到了下层元素身上。如果下层对应的元素是一个链接,那页面就会意外地跳转,如果下层元素绑定了其他事件,此时更会有出乎意料的事情发生。

解决

我们项目当中使用的antd推荐的Fastclick插件,意图解决300ms点击延迟问题,但实际开发当中,发现仍然存在点击穿透的情况(遮罩上方选择学校,遮罩消失之后对应下方的书籍卡片被意外点击,并展示了书籍中的乐谱信息。。。满眼的列表项),起初为了尽快解决问题,在遮罩下方又加了一层透明遮罩绑定click事件(点击消失)当肉盾,事后整理如下:

  • fastclick使用touchend事件模拟click触发,并将真正的click事件屏蔽掉,但在某些(Android)手机上仍然存在不能屏蔽原生click事件的bug,造成点击事件触发两次的问题。
  • 跨页穿透问题解决方案:

    1
    2
    3
    4
    5
    6
    7
    #preventClick { width:100%; height:100%; position:absolute; z-index:1000; top:0; left:0; }
    <body>
    <div id="preventClick"></div>
    </body>
    function onDeviceReady() {
    setTimeout(function(){ $('#preventClick').hide(); }, 300);
    }
  • 本页穿透解决方案:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #preventClick { width:100%; height:100%; position:absolute; z-index:999; top:0; left:0; }
    <container>
    <div class='mask'></div>
    <div id="preventClick"></div>
    </container>
    <script>
    document.getElementById('preventClick').onclick=function(e){
    e.target.style.display="none";
    };
    </script>
  • 由于穿透事件是click延迟造成的,只要将click事件用touch或者tap(由Zepto或KISSY库提供,同样由touch模拟出来的。)

    总结

    用户碰触移动页面之后,需要等待一段时间来判断是不是双击(double tap)动作(双击放大),而不是立即响应单击click,等待的这段时间大约是300ms,因此移动端click有300ms延迟,较好解决方法是使用touchend替换click事件,但注意在手势检测中屏蔽掉对以上模拟的影响。

    知识点补充:

    • pointer-events:none;由CSS3提出,不只是禁用链接hover,打开链接等效果,是真实意义上的将onlick事件去掉了,注意该样式只禁用了鼠标事件,对应的键盘事件并没有被禁用(tab选中,Enter提交等)。
    • PC网页上的大部分操作都是用鼠标的,即响应的是鼠标事件,包括mousedown、mouseup、mousemove和click事件。一次点击行为,可被拆解成:mousedown -> mouseup -> click 三步。

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

实现合理的跨域请求

  1. 1. 问题
  2. 2. 解决
  3. 3. 总结
  4. 4. 知识点补充: