首先说一下我们项目的需求,需要在浏览器中做一个像某X那种长按消息可以撤回的功能。先展示一下最终的效果图。
OK, now let’s look at the code,Warning:全是干货!
<!-- 首先先说文字长按 -->
<div v-html="msgregex(m.message)" class="msgInfo fr" @touchstart='tipStart($event, index)' @touchmove='tipMove()' @touchend='tipEnd()'></div>
该div
标签绑定了三个touch
事件,分别是touchstart、touchmove、touchend
代表着手指按下屏幕,手指在屏幕上滑动,手指从屏幕抬起。
刚开始做长按文字的时候,首先想到了在touchstart
事件的时候,使用event.preventDefault()
阻止浏览器的默认行为,然后setTimeout
启动一个延时器,结果你猜怎么着(此处大坑!!!),我延时器里边的cb,一点都不执行,非常stranger,后来在本文章后引用的博客里边查到,event.preventDefault()
会直接导致setTimeout
不能响应,具体原因目前我也不知道,如果有知道的,可以在评论区评论一起共勉一下!
所以,最后没有用event.preventDefault()
,而是直接使用CSS,直接不让文本被选中,绑定的touch
事件仍旧是使用延时器来。
*{
-webkit-touch-callout:none;
-webkit-user-select:none;
-khtml-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
user-select:none;
}
/** 长按开始 */
tipStart (index) {
clearTimeout(this.touchTimer)
this.touchTimer = setTimeout(() => {
this.touchTimer = 0
this.tipIndex = index
}, 500)
},
/** 长按移动 */
tipMove () {
clearTimeout(this.touchTimer)
this.touchTimer = 0
},
/** 长按结束 */
tipEnd () {
clearTimeout(this.touchTimer)
}
<!-- 再说说图片长按 -->
<div @touchstart.prevent='imgTouchStart($event, index)' @touchend='tipEnd(JSON.parse(m.message).srcpath)'>
<img :src="JSON.parse(m.message).fullpath" alt="" classname="imgMsg">
</div>
我们在浏览器里边长按一张图片是会出现这种情况的,我以Chrome为例
虽然这样长按图片也能触发自己绑定的事件,但是终归用户体验还是很差的。所以这个时候就需要用事件委托
(Good Thing)了。
上边代码我们可以注意到,touch
事件是没有绑定在img
标签上的,而是绑定在父标签div
上边,然后获取一下event
,判断长按的标签的class
名是否是img
标签的class
名,这样我们就可以随意操作了,而且还不会触发像上图的情况!
/** 图片长按开始 */
imgTouchStart (e, index) {
if (e.target.className === 'imgMsg') {
clearTimeout(this.touchTimer)
this.touchTimer = setTimeout(() => {
this.touchTimer = 0
this.tipIndex = index
}, 500)
}
},
/** 图片长按结束 */
tipEnd(src = undefined) {
clearTimeout(this.touchTimer)
if (this.touchTimer !== 0) {
if (src) {
this.showImg(src)
}
}
}
因为自己做的时候,网上资料较少,然后自己只能摸索前进,所以写下本篇,希望对你有所帮助,少踩一些坑,一起共勉学习!
https://www.cnblogs.com/zxj95121/p/7928510.html