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

时间:2020-09-18  来源:js教程  阅读:


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

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

修改需要

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

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

监听的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);
增加touchmove的监听,用于令长按无效

this.el.addEventListener("touchmove",function(e) {
    window.longEnable = false;
},false);
修改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;
    }
},
修改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 {
        // 短击...
    }
}

vue-tap-click.js文件如下

/**
 * Created by 二哲 on 15/12/6.
 */
/*
* 不带参数指令
* v-tap=handler
* or
* 带参数指令
* v-tap=handler($index,el,$event)
*
* !!!新增!!!
* 把tapObj对象注册在原生event对象上
* event.tapObj拥有6个值
* pageX,pageY,clientX,clientY,distanceX,distanceY
* 后面2个分别的手指可能移动的位置(以后可用于拓展手势)
*
* */
;(function() {
    var vueTap = {};
    vueTap.install = function(Vue) {
        Vue.directive("tap", {
            isFn : true,
            acceptStatement : true,
            bind : function() {
                 //bind callback
            },
            update : function(fn) {
                var self = this;
                    self.tapObj = {};

                if(typeof fn !== "function") {
                    return console.error("The param of directive "v-tap" must be a function!");
                }
                self.handler = function(e, isLong) { //This directive.handler
                    e.tapObj = self.tapObj;
                    // 用全局变量记录是否长按 -start
                    if (isLong) {
                        e.isLong = true
                    }
                    // 用全局变量记录是否长按 -end
                    fn.call(self,e);
                };
                if(self.isPC()) {
                    self.el.addEventListener("click",function(e) {
                        e.preventDefault();
                        fn.call(self,e);
                    },false);
                } else {
                    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);
                    this.el.addEventListener("touchmove",function(e) {
                        //e.preventDefault();
                        window.longEnable = false;
                    },false);
                    this.el.addEventListener("touchend",function(e) {
                        //e.preventDefault();
                        self.touchend(e,self,fn);
                    },false);
                }
            },
            unbind : function() {},
            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;
                }
            },
            isPC : function() {
                var uaInfo = navigator.userAgent;
                var agents = ["Android", "iPhone", "Windows Phone", "iPad", "iPod"];
                var flag = true;
                for (var i = 0; i < agents.length; i++) {
                    if (uaInfo.indexOf(agents[i]) > 0) { flag = false; break; }
                }
                return flag;
            },
            touchstart : function(e,self) {
                var touches = e.touches[0];
                var tapObj = self.tapObj;
                tapObj.pageX = touches.pageX;
                tapObj.pageY = touches.pageY;
                tapObj.clientX = touches.clientX;
                tapObj.clientY = touches.clientY;
                self.time = +new Date();
            },
            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
               
                /*
                if (self.isTap(tapObj)){
                    self.handler(e);
                */
            }
        });
    };

    if (typeof exports == "object") {
        module.exports = vueTap;
    } else if (typeof define == "function" && define.amd) {
        define([], function(){ return vueTap })
    } else if (window.Vue) {
        window.vueTap = vueTap;
        Vue.use(vueTap);
    }

})();

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

http://m.bbyears.com/wangyezhizuo/99355.html

推荐访问:
相关阅读 猜你喜欢
本类排行 本类最新