移动端手势研究

移动端手势的实现

首先这次的手势实现是一个漫长的过程,最开始的需求是右滑手势的识别,很简单直接贴代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
touchStart (e) {
// 记录初始位置
e.preventDefault() // 阻止默认事件,滚动等
this.startX = e.touches[0].clientX // 记录滑动开始的位置
},
touchEnd (e) {
e.preventDefault() // 阻止默认事件
// 记录结束位置
this.endX = e.changedTouches[0].clientX
// 左滑
if (this.startX - this.endX > 80) {
}
// 右滑
if (this.startX - this.endX < -80) {
}
this.startX = 0
this.endX = 0
},

手势与点击事件冲突

手势的实现十分简单,但当加上touchstart和touchend的时间监听后,发现无法再触发click事件了,
当时因为时间很紧,于是采取了将那个页面的所有click事件换成了touchend事件。
问题貌似是解决了

用touchend事件替换click事件的弊端,以及影响click事件无法触发的原因

替换了click事件后,我自以为耍了小聪明,节省了大把的时间。
但半年后,用户反映当滑动的时候正好点在原来点击事件的按钮上,会直接出发按钮上的事件。
错误很容易理解,单纯就是触发了touchend事件。原来的小聪明看来是行不通了。只好研究一下影响click事件的根本原因了。

经过查阅资料,我发现原来click事件的触发过程是这样的:
touchstart=>touchmove=>touchend=>click
如果在点击屏幕的时候手指滑动的话,是不会触发click事件的!!
而我的代码阻止了touchstart、touchend的默认行为,浏览器就判定没有触发touchstart以至于没有触发点击事件了。
但是如果不加,某些浏览器有时会无法识别touchend事件(200ms超时导致内核不一定会一直处理touchmove事件)
问题也要解决,难道要每个click事件分别监听touchstart和touchend的事件来判断到底是点击还是滑动吗?
这样可行,但是很麻烦,我就是想用click!

解决方法

想了一下,浏览器之所以采取这个机制应该是为了给用户加上后悔药机制,当用户已经点了某个按钮后发现点错了,为了反悔只要将手指移到其他地方放开就相当于没有点击了。
了解了设计的目的,就能明白手机端点击的判定了:只要绑定上click事件的dom既有touchstart又有touchend事件就能触发click了。
那么很简单,在touchmove上加上e.preventDefault()不就行了?代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
touchStart (e) {
// 记录初始位置
//e.preventDefault() // 阻止默认事件,滚动等
this.startX = e.touches[0].clientX // 记录滑动开始的位置
},
touchmove (e) {
this.endX = e.changedTouches[0].clientX;
if (this.startX - this.endX > -80&&this.startX - this.endX < 80) {
e.preventDefault()
}
},
touchEnd (e) {
//e.preventDefault() // 阻止默认事件
// 记录结束位置
this.endX = e.changedTouches[0].clientX
// 左滑
if (this.startX - this.endX > 80) {
}
// 右滑
if (this.startX - this.endX < -80) {
this.$router.push({name:"Mealreservation"})
}
this.startX = 0
this.endX = 0
}

监听完touchmove事件后,果然大功告成。

当然,假如还有问题这篇文章还会更新的(抹泪)。。。