Vue.js 移动端 Web App 点击穿透问题解决方案

描述

在近期的一个移动端项目中,有一个页面须要有弹框提示,而且这个弹框经过关闭按钮关闭。页面当中使用了 iScroll 来实现页面局部滚动,在 iScroll 的配置当中把 tap 和 click 事件都开启了。
代码以下:html

this.myScroll = new IScroll(this.$refs.wrapper, {  mouseWheel: true,  click: true,  tap: true})

在实现过程当中,遇到了一个奇怪的问题,因为按钮的位置与弹框右上角的关闭按钮位置一致,当我点击按钮时,弹框一闪而过。vue

效果以下:
效果图git

缘由

什么是点击穿透?

假如页面上有两个元素A和B。B元素在A元素之上。咱们在B元素的touchstart事件上注册了一个回调函数,该回调函数的做用是隐藏B元素。咱们发现,当咱们点击B元素,B元素被隐藏了,随后,A元素触发了click事件。github

经过上网查找有关资料,翻阅了移动端的书籍,发如今手机端中,事件的触发顺序为:touchstart -> touchmove -> touchend,而 click 事件有 300ms 的延迟,当 touchstart 事件把B元素隐藏以后,隔了300ms,浏览器触发了 click 事件,可是此时B元素不见了,因此该事件被派发到了A元素身上。若是A元素是一个连接,那此时页面就会意外地跳转。segmentfault

解决方案

1. 改用 touch 事件

因为项目使用的是 Vue.js,这里就提供一下 Vue.js 的解决方法。使用了 vue-tap 的一个插件,具体使用方法参看官方文档,在须要点击事件的时候,经过 v-tap 指令来绑定。浏览器

// main.jsimport vueTap from 'v-tap' // 引入插件Vue.use(vueTap) // 全局注册
v-tap="{methods:showReceiveModel}" // 在元素上绑定事件

2. 使用 fastclick 插件

这个也是在网上看到的,也能够解决点透问题,使用方法能够看 fastclick 的文档,在这里提供一下 Vue.js 的引入及使用app

import FastClick from 'fastclick'; // 引入插件FastClick.attach(document.body, options); // 使用 fastclick

最终没有使用这个方案是由于有一些小 bug ,如 Fastclick 致使click事件触发两次的问题ide

其余

tap 一词

对于 tap 这个词,用过 Zepto 或 KISSY 等移动端js库的人确定对tap事件不陌生,作PC页面时绑定 click,相应地手机页面就绑定 tap。但原生的 touch 事件自己是没有 tap 的,js库里提供的tap事件都是模拟出来的。函数

手机上响应 click 事件会有300ms的延迟,那么这300ms究竟是干吗了?浏览器在 touchend 后会等待约300ms,缘由是判断用户是否有双击(double tap)行为。若是没有 tap 行为,则触发 click 事件,而双击过程当中就不适合触发 click 事件了。由此能够看出 click 事件触发表明一轮触摸事件的结束。gradle

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

参考

博文

书籍

  • 《移动 Web 手册》

相关文章
相关标签/搜索