vue.js 框架中实现手指点击事件 v-tap ,自定义 self 与 long 修饰符

要实现手指的 tap 动作,首先找到的应该是 vue-touch 插件,项目地址:Github,其基于 hammerjs,能除了点击以外,还能监听按住、滑动、双指收缩、双指旋转等动作,十分强大,但是没有对事件修饰进行定义,即无法阻止事件冒泡。

我找到另一个 tap 插件,来自 MeCKodo 的 vue-tap,项目地址:Github,十分简洁的一个插件,扩展功能也比较方便,有提供stopprevent修饰符,所以我用了它。


修改需要

由于vue-tap提供的stopprevent修饰符会在touchstart时就禁止了冒泡,导致我项目中使用的iscroll滚动会失效,于是我自定义了self修饰符,用于一旦被tap方法响应过,将不再进行向应的伪防冒泡修饰符,以及用于监控长按的long修饰符。

我修改的四个代码段如下:

  1. 监听的touchstart动作,增加全局变量tapDone用于记录tap是否已被触发过,longEnable用于记录长按是否有效,longTimer用于记录长按计时器

    我本来是用self代替window的,毕竟全局变量有可能造成污染,但我tap动作中有路由切换动作,插件被重新加载后self中所有变量都会被重置,造成变量防冒泡失败,所以,最后我还是用了全局变量

     this.el.addEventListener('touchstart',function(e) {
         // 增加self修饰符-start by COoL
         if(self.modifiers.self && window.tapDone)
             return;
         window.tapDone = true;
         setTimeout(function(){
             window.tapDone = false;
         },200);
         // 增加self修饰符-end
         // 加入long修饰符实现长按动作-start by COoL
         if (self.modifiers.long) {
             window.longEnable = true;
             window.longTimer = setTimeout(() => {
                 self.touchend(e,self,fn);
             }, 600)
         }
         // 加入long修饰符实现长按动作-end
         if(self.modifiers.stop)
             e.stopPropagation();
         if(self.modifiers.prevent)
             e.preventDefault();
         self.touchstart(e,self);
     },false);
    
  2. 增加touchmove的监听,用于令长按无效

     this.el.addEventListener('touchmove',function(e) {
         window.longEnable = false;
     },false);
    
  3. 修改isTap方法,把boolean返回值改为int,因为要增加长按类型

     isTap : function() {
         var self   = this;
         if(self.el && self.el.disabled){
             return 0; // 原为false
         }
         var tapObj = this.tapObj;
         if (Math.abs(tapObj.distanceX) >= 2 || Math.abs(tapObj.distanceY) >= 2) {
             // 手指有移动,作废
             return 0;
         } else if (this.time < 150) {
             // 快速点击
             return 1;
         } else if (this.time >= 600) {
             // 长按
             return 2;
         } else {
             // 时间有误,作废
             return 0;
         }
     },
    
  4. 修改touchend方法,清空长按计时,判断点击还是长按,是否有效

     touchend : function(e,self) {
         var touches = e.changedTouches[0];
         var tapObj = self.tapObj;
         self.time = +new Date() - self.time;
         tapObj.distanceX = tapObj.pageX - touches.pageX;
         tapObj.distanceY = tapObj.pageY - touches.pageY;
         // 加入long修饰符实现长按动作-start by COoL
         // 清除长按计时
         clearTimeout(window.longTimer)
         // 获取是否长按或无效
         var tapType = self.isTap(tapObj);
         if (tapType === 0) {
             // 无效
             return;
         }
         if (tapType === 1) {
             // 短击
             self.handler(e);
             return;
         }
         if (self.modifiers.long && tapType === 2 && window.longEnable) {
             // 允许长按且是长按且首次触发且未移动过
             window.longEnable = false;
             self.handler(e, true)
             return;
         }
         // 加入long修饰符实现长按动作-end
     }
    

最后,看看调用的方法

v-tap.self.long="goOrDel($index, $event)"

self使冒泡无效,long使允许长按,而goOrDel方法中,$event.isLong将用于区分短击还是长按

goOrDel: function (ind, e) {
    if (e.isLong) {
        // 长按...
    } else {
        // 短击...
    }
}

我修改后地文件:https://github.com/coolhihi/vue-tap/blob/master/vue-tap-click.js

若您觉得我的博文对您有帮助,欢迎点击下方按钮对我打赏
打赏