关于"touchstart与click同时触发"问题

点击事件可以分解成多个事件:

在移动端,手指点击一个元素,会经过:touchstart --> touchmove -> touchend -->  click


 

由于移动设备能够同时识别 touchstart click 事件,因此当用户点击目标元素时,绑定在目标元素上的 touchstart 事件与 click 事件(约300ms后)会依次被触发,也就是说,我们所绑定的回调函数会被执行两次!

解决方案

方法一:使用事件对象中的 preventDefault 方法

preventDefault 方法的作用在于:阻止元素默认事件行为的发生,但有意思的是,当我们在目标元素同时绑定 touchstart 和 click 事件时,在 touchstart 事件回调函数中使用该方法,可以阻止后续 click 事件的发生。

 

const Button = document.getElementById("targetButton")
Button.addEventListener("touchstart", e => {
 e.preventDefault()
 console.log("touchstart event!")
})
 
Button.addEventListener("click", e => {
 e.preventDefault()
 console.log("click event!")
})

 

方法二:基于功能检测绑定事件

通过判断浏览器是否支持 touchstart 事件来封装元素的点击事件,这样客户端会根据当前环境判定元素应该绑定的事件类型。

const Button = document.getElementById("targetButton")
const clickEvent = (function() {
 if ('ontouchstart' in document.documentElement === true)
     return 'touchstart';
 else
     return 'click';
})();
 
Button.addEventListener(clickEvent, e => {
 console.log("things happened!")
});

VUE解决方案:

HTML:

<div class="comment-text" 
     @touchstart.prevent="gtouchstart(XXX)"
     @touchend.prevent="triggerReply(XXXX)">
     {{ item.content}}
 </div>

JS:

data: function () {
    return {
          Loop: 0
      };
 },
methods: {
    gtouchstart: function (XXXX) {
        let self = this;
        //执行长按的内容
        self.Loop = setTimeout(function () {
            self.Loop = 0;
            //XXXXXXXXXXXXXXX
        }, 500);
        return false;
    },
    triggerReply: function (XXXX) {
        let self = this;
        clearTimeout(self.Loop);
        //这里click内容
        if (self.Loop !== 0) {
             //XXXXXXXXXXXXXXX
        }
        return false;
    }
}

添加 touchstart.prevent,组织click事件。

 

posted @ 2020-04-05 17:21  心无引擎,眼无流派  阅读(1018)  评论(0编辑  收藏  举报