vue 自定义点击事件
2017-12-27 11:15
393 查看
我们在项目开发中使用vue的时候发现vue内置的click事件在移动端使用会有300毫秒的点击延迟,所以我们就自己写了一个点击的自定义事件,希望对各位有所帮助,不足之处希望各位能够及时沟通。
废话就不多说了,直接贴代码了:(function(){ var touchSupport = (('ontouchstart' in window) || (navigator.MaxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0)) /(Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone)/i.test(navigator.userAgent); var touchSpace = {}; // 获取支持的事件类型 var touchEventType = (function(){ return touchSupport ? { start: 'touchstart', move: 'touchmove', end : 'touchend', cancel: 'touchcancel' } : { start : 'mousedown', move: 'mousemove', end : 'mouseup', cancel: 'mousecancel' } })(); // 绑定事件 var touchEventAdd = function(el, handler, capture){ el.addEventListener(touchEventType.start, handler.start, capture); el.addEventListener(touchEventType.move, handler.move, capture); el.addEventListener(touchEventType.end, handler.end, capture); el.addEventListener(touchEventType.cancel, handler.end, capture); }; // 解除绑定事件 var touchEventRemove = function(el, handler){ el.removeEventListener(touchEventType.start, handler.start); el.removeEventListener(touchEventType.move, handler.move); el.removeEventListener(touchEventType.end, handler.end); el.removeEventListener(touchEventType.cancel, handler.end); }; // 判断事件类型 var touchType = function(start, end){ // 初始化变量 var type = null; var direction = null; var ratio = window.devicePixelRatio; var during = end.T - start.T; var h = (end.X - start.X)/ratio; var v = (end.Y - start.Y)/ratio; var absh = Math.abs(h); var absv = Math.abs(v); var move = Math.sqrt(Math.pow(h,2) + Math.pow(v,2)); // 判断事件按类型 switch (true){ case (during < 32): break; case (move < 3 && during > 740): type = 'holdtap'; break; case (move < 3 && during < 300): type = 'tap'; break; case (move > 5 && during < 300): type = 'swipe'; break; default: break; } switch (type == 'swipe'){ case (absv < 5 && absh > 5 && h > 0 ): direction = 'right'; break; case (absv < 5 && absh > 5 && h < 0 ): direction = 'left'; break; case (absv > 5 && absh < 5 && v > 0 ): direction = 'down'; break; case (absv > 5 && absh < 5 && v < 0 ): direction = 'up'; break; default: break; } return { type: type, direction: direction, move: move, during: during }; }; // 事件调节器 var touchModifier = function (dom, e, modifiers) { modifiers.stop && e.stopPropagation(); modifiers.prevent && e.preventDefault(); if(modifiers.self && dom !== e.target){ return false; } return true; }; // 触控事件类 var touchHandler = function(type){ return { start: function(e){ // 初始化变量 var key = this['vue-touch-id']; var data = touchSpace[key][type]; var modifiers = data.modifiers; var method = data.method; var start = data.start; // 初始化触摸位置 start.X = touchSupport ? e.touches[0].pageX : e.screenX; start.Y = touchSupport ? e.touches[0].pageY : e.screenY; start.T = touchTimestamp(); // 如果调节器停止事件 if (!touchModifier(this,e,modifiers)){ return false; } // 如果是拖拽,则触发 start if (type === 'drag') { e.source = this; e.touchPoint = start; method['start'].apply(e, [e].concat(data.params)); } // 如果是长按,则通过定时器实现 if (type === 'holdtap'){ if (data.timer) { clearTimeout(data.timer); } data.timer = setTimeout(function () { method.apply(e, [e].concat(data.params)); data.timer = 0; }, 750); } }, move: function(e){ // 初始化变量 var key = this['vue-touch-id']; var data = touchSpace[key][type]; var modifiers = data.modifiers; var method = data.method; var move = { X : touchSupport ? e.changedTouches[0].pageX : e.screenX, Y : touchSupport ? e.changedTouches[0].pageY : e.screenY, T : touchTimestamp() }; if (type === 'drag') { e.source = this; e.touchPoint = move; method['move'].apply(e, [e].concat(data.params)); e.preventDefault(); return false; } else { fixedTouchScrollBug(); } }, end: function(e){ // 初始化手指位置 var key = this['vue-touch-id']; var data = touchSpace[key][type]; var modifiers = data.modifiers; var method = data.method; var start = data.start; var end = { X : touchSupport ? e.changedTouches[0].pageX : e.screenX, Y : touchSupport ? e.changedTouches[0].pageY : e.screenY, T : touchTimestamp() }; var action = touchType(start,end); // 如果调节器停止事件 if(!touchModifier(this,e,modifiers)){ return false; } // 如果正在滚动中 if ( touchScrolling === true){ return false; } // 如果是拖拽事件 if (type === 'drag') { e.source = this; e.move = action.move; e.during = action.during; e.touchPoint = end; method['end'].apply(e, [e].concat(data.params)); } // 判断事件类型 if (!type || action.type !== type) { return false; } // 设置滑动方向 if (type === 'swipe'){ e.direction = action.direction; } // 如果是其他事件 if (type !== 'holdtap' && type !== 'drag'){ e.source = this; method.apply(e, [e].concat(data.params)); } e.stopImmediatePropagation(); return false; } }; }; // 获取随机标识 var touchRandomKey = function(){ return 'vue-touch-' + (Math.random() + '').replace(/\D/g, ''); }; // 获取时间戳 var touchTimestamp = function(){ return new Date().getTime(); }; Vue.directive( 'touch', { bind:function(el, binding) { // 初始化变量 var key = ''; var type = binding.arg; var data = binding.value || {}; var modifiers = binding.modifiers; var capture = !!modifiers.capture; var method = ( typeof data === 'function' ? data : ( data.event || function(){} ) ); var params = ( data.params || [] ); var handler = new touchHandler(type); // 初始化对象标识 if (el.hasOwnProperty('vue-touch-id')){ key = el['vue-touch-id']; } else { key = el['vue-touch-id'] = touchRandomKey(); touchSpace[key] = {}; } // 如果是拖拽方法 if (type === 'drag') { method = { start: data.start || function(){}, move: data.move || function(){}, end: data.end || function(){} } } // 初始化事件容器 touchSpace[key][type] = { modifiers: modifiers, method: method, params: params, handler: handler, start : { X : 0, Y : 0, T : 0 }, timer : 0 }; // 绑定事件 touchEventAdd(el,handler,capture); }, update: function(el, binding){ var key = el['vue-touch-id']; var type = binding.arg; var params = ( binding.value.params || [] ); touchSpace[key][type].params = params; }, unbind:function(el){ // 初始化变量 var key = el['vue-touch-id']; var data = touchSpace[key]; // 循环绑定的事件, 接触绑定 for (var item in data){ if (data.hasOwnProperty(item) && item){ touchEventRemove(el,data[item].handler); } } // 释放变量内存 delete touchSpace[key]; } }); // 修复滚动条与 touch 事件的冲突 var timer, lastScrollTop = 0, touchScrolling = false; var fixedTouchScrollBug = function(){ var currentScrollTop = document.body.scrollTop; if ( lastScrollTop == currentScrollTop ) { if (touchScrolling === true){ timer = window.setTimeout(function(){ touchScrolling = false; }, 100); } } else { touchScrolling = true; lastScrollTop = currentScrollTop; } }; window.setInterval(fixedTouchScrollBug, 10 })();
以上则是事件的方法,在页面中调用的方式也比较方便,与click的用法基本上可以说是大同小异,下面则是页面中使用的方法:
<div class="best" v-touch:tap="{ event: method, params: [ parameter ] }">点击</div> <div class="best" v-touch:tap="{ event: method, params: [] }">点击</div>
点击事件的页面调用方法如上: event是调用的点击时调用的方法名称,params是调用方法时需要的参数,params中可以传对象,数组,字符串,数字。
相关文章推荐
- vue自定义移动端touch事件之点击、滑动、长按事件
- vue自定义移动端touch事件,点击、滑动、长按事件
- 利用自定义属性实现js点击事件 委托
- 自定义cell中的按钮点击事件
- 自定义UITableViewCell上的按钮点击事件处理
- 自定义CursorAdapter,实现ListView中动态加载button,和点击事件
- 自定义图例点击事件
- iOS 一一 自定义cell按钮的点击事件(通知机制)
- 隐藏自定义的tabbar之后,push到B视图,B视图的键盘工具条无法响应点击事件
- Android自定义注解与注解器实现点击事件绑定
- echarts自定义图例的点击事件
- Dialog 自定义使用3(回调点击事件)
- Android自定义按钮点击事件和长按事件的区分
- 自定义adapter的基础上Listview优化方案以及几个小错误(checkbox吃掉点击事件以及对象重复问题)
- [安卓开发]弹幕滚幕效果自定义View之BarrageView|支持点击事件|隐藏不滞留|颜色随机|大小速度范围随机
- 自定义封装导航栏左右按钮点击事件和特定风格的控制器供多个控制器继承—— 当很多导航页面有相似的导航条时
- 项目——用自定义View在屏幕的左侧写上a~z,并加上点击事件
- 多个自定义覆盖物注册点击事件,点击某个覆盖物后获得它的坐标
- jQuery自定义元素右键点击事件