移动端的touch事件和click事件遇到的坑
(移动端项目中)长按聊天消息,出现一个弹出层,进行消息撤回操作,点击弹出层之外的其他地方需要隐藏该弹出层。记录下这里遇到的坑。
项目需求:
(移动端项目中)长按聊天消息,出现一个弹出层,进行消息撤回操作,点击弹出层之外的其他地方需要隐藏该弹出层。
基础html代码:
1 | <div> |
需求实现:
1 | // 通过定时器,只有长按超过500ms是才进行需要的操作 |
问题一:
在安卓中,上面的代码能实现我们的需求,但是,在IOS中,长按松开后,弹出层就立马关闭了!!!****
了解了下touch和click事件:
touchstart:
- touchstart 手指触碰开始就能触发
click:
- 1.手指触碰
- 2.手指未在屏幕上移动
- 3.在这个dom上手指离开屏幕
- 4.触摸和离开屏幕之间的时间间隔较短
上网一顿搜索发现touch和click的执行顺序:
touchstart –> touchmove –> touchend –> touchcancel –> click
所以,执行完touch事件后会执行click事件,在ios中就会出现长按松开后就会关闭弹出层。这里我们需要阻止touch事件的默认行为使用event.preventDefault()
修改下keepPress中的代码
1 | keepPress(event){ |
这样代码就能满足我们的需求了。
问题二:
当我们发送的消息是图片消息时,我们需要点击图片放大,长按图片也出现撤销的弹出层。通过前面的分析,当click和touch事件同时存在时会先触发touch,再触发click**** 。因为我们阻止了touch事件的默认行为,所以,我们点击图片的时候并不会触发click事件,图片也就不会放大。
这里我们需要在touchend中做处理,如果长按时间短,就用代码触发图片的点击事件,长按时间长,就不触发图片的点击事件。
修改前面的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
keepPress(event){
event.preventDefault()
this.pressTime = 0 // 清0计数器
$('.press-operation').hide() // 每次长按会先隐藏所有的弹出层
let nodeEl = event.currentTarget.parentElement.firstElementChild
this.pressTimer = setInterval(() => {
this.pressTime = this.pressTime + 1
nodeEl.style.display = 'block'
},500)
},
keepPressEnd(event){
let el = event.currentTarget.getElementsByClassName('img')[0]
clearInterval(this.pressTimer)
if(this.pressTime < 1){ // 长按时间不足500ms时,触发点击事件
if(el){
el.click()
}
}
},
到此为止,应该是满足了我的需求了
感谢您的阅读
如有不对,欢迎指正。如有其他实现方法,欢迎留言讨论~