├── README.MD ├── demo.html ├── dist ├── index.js └── index.min.js ├── gulpfile.js ├── package.json └── src └── index.js /README.MD: -------------------------------------------------------------------------------- 1 | # Vue 2.0 移动设备指令 ( Vue touch directive ) 2 | 3 | > 轻量级 Vue 2.0 移动触摸事件自定义指令;
4 | > 预设 tap up right down left long 触摸操作类型;
5 | > 完整支持 self once prevent capture stop 事件修饰符;
6 | > 自定义指令方法传参最佳实例;
7 | > 资源合理释放;
8 | 9 | 10 | ## 安装: 11 | 12 | > * ES6 13 | 14 | ``` bash 15 | 16 | npm install vue-directive-touch --save; 17 | 18 | ``` 19 | 20 | ```javascript 21 | 22 | import touch from 'vue-directive-touch'; 23 | Vue.use(touch); 24 | 25 | ``` 26 | 27 | > * 直接引入: 28 | ```html 29 | 30 | 31 | ``` 32 | 33 | 34 | ## 使用 How to use: 35 | 36 | 37 | ### 常规 38 | 39 | 40 | ```html 41 | 42 |

绑定事件

43 | 44 | 45 |

绑定事件

46 | 47 | ``` 48 | 49 | ```javascript 50 | new Vue({ 51 | el: "dom", 52 | methods : { 53 | eventFun : function() { 54 | //事件方法 55 | } 56 | } 57 | }); 58 | ``` 59 | 60 | ## 传参 61 | 62 | ```html 63 | 72 | ``` 73 | 74 | ```javascript 75 | new Vue({ 76 | el: "dom", 77 | methods : { 78 | /* 自定义指令方法: 附带参数 */ 79 | eventFunWithParam : function(index,item) { 80 | return function(event, start, end) { 81 | /* 82 | * event 为事件实例 83 | * start end 分别包含事件起始信息: X --> 横坐标 | Y --> 纵坐标 | T --> 时间戳 84 | * index、item 为方法传参 85 | */ 86 | 87 | } 88 | }, 89 | /* 自定义指令方法: 无传参 */ 90 | eventFunNoParam : function(event, start, end) { 91 | /* 92 | * event 为事件实例 93 | * start end 分别包含事件起始信息: X --> 横坐标 | Y --> 纵坐标 | T --> 时间戳 94 | * index、item 为方法传参 95 | */ 96 | }, 97 | /* 原生 Vue 事件方法 */ 98 | orginalFun : function(index,item,event) { 99 | /* 100 | * event 为事件实例 101 | * index、item 为方法传参 102 | */ 103 | } 104 | 105 | } 106 | }); 107 | ``` 108 |

109 | 110 | 111 | ## 事件类型: 112 | 113 | > 单击: v-touch:tap
114 | > 长按: v-touch:long
115 | > 左滑: v-touch:left
116 | > 右滑: v-touch:right
117 | > 上滑: v-touch:up
118 | > 下滑: v-touch:down
119 | 120 |

121 | 122 | ## 事件修饰符 123 | ##### 事件修饰符释义参照 Vue [官方文档](https://cn.vuejs.org/v2/guide/events.html#事件修饰符)


124 | 125 | ## Vue 1.0 与 2.0 自定义指令开发的差异: 126 | > Vue 2.0 版本自定义指令 API 相比 1.0 全部更改,在自定义指令开发层面完全不兼容,使用层面主要差异为:"自定义指令方法的传参"
127 | > 例:
128 | > 在 Vue 1.0 中可以实现以下自定义指令
129 | > v-touch="fun($index,param)"
130 | > Vue 2.0 的指令机制会直接将其解析为 expression,也就是自定义指令中的 fun($index,param) 会被直接执行,传递到生命周期中的值是 fun($index,param) 执行的结果;
131 | > Vue 2.0 相关机制更改的原因引用文档中的解释:" 有的情况下,你仍然需要对纯 DOM 元素进行底层操作,这时候就会用到自定义指令",另外一个层面,也可以保持指令传递方法逻辑处理的统一; 132 | 133 | 134 | ## License 135 | 136 | MIT 137 | 138 | -------------------------------------------------------------------------------- /demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Vue 2.0 v-touch Demo 6 | 27 | 94 | 95 | 96 | 97 |
98 | 99 |
107 |

按钮

108 |
109 | 110 |
111 |
112 |

支持事件指令包括: 点击、长按、左滑、右滑、上滑、下滑

113 |
114 |

当前事件类型为:

115 |
116 |
117 | 118 |
119 | 120 | 121 | 122 | 141 | 142 | -------------------------------------------------------------------------------- /dist/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; 4 | 5 | !function () { 6 | var Helper = { 7 | getTimestamp: function getTimestamp() { 8 | return new Date().getTime(); 9 | }, 10 | getRandomKey: function getRandomKey() { 11 | return 'vue-touch-' + (Math.random() + '').replace(/\D/g, ''); 12 | }, 13 | getType: function getType(start, end) { 14 | var type = null; 15 | var ratio = Math.min(2, window.devicePixelRatio); 16 | var during = end.T - start.T; 17 | var h = (end.X - start.X) / ratio; 18 | var v = (end.Y - start.Y) / ratio; 19 | var absh = Math.abs(h); 20 | var absv = Math.abs(v); 21 | var move = Math.sqrt(Math.pow(h, 2) + Math.pow(v, 2)); 22 | switch (true) { 23 | case during < 3: 24 | break; 25 | case during > 500 && move < 20: 26 | type = 'long'; 27 | break; 28 | case move < 6: 29 | type = 'tap'; 30 | break; 31 | case h > 0 && absv < 35: 32 | type = 'right'; 33 | break; 34 | case h < 0 && absv < 35: 35 | type = 'left'; 36 | break; 37 | case v > 0 && absv > absh: 38 | type = 'down'; 39 | break; 40 | case v < 0 && absv > absh: 41 | type = 'up'; 42 | break; 43 | default: 44 | } 45 | return type; 46 | }, 47 | getEventName: function getEventName() { 48 | return isMobile ? { 49 | start: 'touchstart', 50 | end: 'touchend' 51 | } : { 52 | start: 'mousedown', 53 | end: 'mouseup' 54 | }; 55 | }, 56 | attachEvent: function attachEvent(el, handler, capture) { 57 | var event = Helper.getEventName(); 58 | el.addEventListener(event.start, handler.start, capture); 59 | el.addEventListener(event.end, handler.end, capture); 60 | }, 61 | detachEvent: function detachEvent(el, handler) { 62 | var event = Helper.getEventName(); 63 | el.removeEventListener(event.start, handler.start); 64 | el.removeEventListener(event.end, handler.end); 65 | } 66 | }; 67 | var vueTouch = {}; 68 | var isMobile = 'ontouchstart' in window || navigator.MaxTouchPoints > 0 || navigator.msMaxTouchPoints > 0 || /(Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone)/i.test(navigator.userAgent); 69 | var modifierRules = function modifierRules(dom, e, modifiers) { 70 | /* 禁止冒泡 */ 71 | modifiers.stop && e.stopPropagation(); 72 | /* 阻止默认事件 */ 73 | modifiers.prevent && e.preventDefault(); 74 | /* 元素本身事件 */ 75 | if (modifiers.self && dom !== e.target) { 76 | return false; 77 | } 78 | return true; 79 | }; 80 | var newHandler = function newHandler(type) { 81 | return { 82 | start: function start(e) { 83 | var key = this['vue-touch-id']; 84 | var data = workSpace[key][type]; 85 | var method = data.method; 86 | var modifiers = data.modifiers; 87 | var start = data.start; 88 | if (isMobile) { 89 | start.X = e.touches[0].pageX; 90 | start.Y = e.touches[0].pageY; 91 | } else { 92 | start.X = e.screenX; 93 | start.Y = e.screenY; 94 | } 95 | start.T = Helper.getTimestamp(); 96 | /* 修饰符策略 */ 97 | if (!modifierRules(this, e, modifiers)) { 98 | return false; 99 | } 100 | /* 周期开始 */ 101 | data.cycle = 1; 102 | /* 长按计时器 */ 103 | if (type === 'long') { 104 | if (data.timer) clearTimeout(data.timer); 105 | data.timer = setTimeout(function () { 106 | data.cycle < 3 && method(e); 107 | data.timer = 0; 108 | }, 300); 109 | } 110 | }, 111 | end: function end(e) { 112 | var end = { 113 | X: 0, 114 | Y: 0, 115 | T: Helper.getTimestamp() 116 | }; 117 | if (isMobile) { 118 | end.X = e.changedTouches[0].pageX; 119 | end.Y = e.changedTouches[0].pageY; 120 | } else { 121 | end.X = e.screenX; 122 | end.Y = e.screenY; 123 | } 124 | 125 | var key = this['vue-touch-id']; 126 | var data = workSpace[key][type]; 127 | var method = data.method; 128 | var modifiers = data.modifiers; 129 | var start = data.start; 130 | /* 周期完成 */ 131 | data.cycle = 3; 132 | if (!type || Helper.getType(start, end) !== type) return false; 133 | /* 修饰符策略 */ 134 | if (!modifierRules(this, e, modifiers)) { 135 | return false; 136 | } 137 | /* 事件执行 */ 138 | type !== 'long' && method(e, start, end); 139 | /* 单次执行结束后释放事件及数据 */ 140 | if (modifiers.once) { 141 | Helper.detachEvent(this, data.handler); 142 | delete workSpace[key][type]; 143 | } 144 | /* 执行 afterEvent Hook */ 145 | if (afterEvent !== null) { 146 | afterEvent(this, type, e); 147 | } 148 | } 149 | }; 150 | }; 151 | var afterEvent = null; 152 | var workSpace = {}; 153 | 154 | vueTouch.install = function (Vue, options) { 155 | if (options && options.afterEvent && typeof options.afterEvent === 'function') afterEvent = options.afterEvent; 156 | Vue.directive('touch', { 157 | bind: function bind(el, binding) { 158 | var type = binding.arg; 159 | var modifiers = binding.modifiers; 160 | var capture = !!modifiers.capture; 161 | var method = binding.value; 162 | var key = ''; 163 | 164 | if (typeof binding.value !== 'function' || !binding.arg) { 165 | return console.error('[Vue warn]: Invalid parameter, Expected Function.'); 166 | } 167 | 168 | if (el.hasOwnProperty('vue-touch-id')) { 169 | key = el['vue-touch-id']; 170 | } else { 171 | key = el['vue-touch-id'] = Helper.getRandomKey(); 172 | workSpace[key] = {}; 173 | } 174 | var handler = newHandler(type); 175 | workSpace[key][type] = { 176 | method: method, 177 | modifiers: modifiers, 178 | handler: handler, 179 | start: { 180 | X: 0, 181 | Y: 0, 182 | T: 0 183 | }, 184 | timer: 0, 185 | cycle: 0 186 | }; 187 | Helper.attachEvent(el, handler, capture); 188 | }, 189 | update: function update(el, binding) { 190 | var type = binding.arg; 191 | var method = binding.value; 192 | var key = el['vue-touch-id']; 193 | var data = workSpace[key]; 194 | if (data.hasOwnProperty(type)) { 195 | data[type].method = method; 196 | } 197 | }, 198 | unbind: function unbind(el) { 199 | var key = el['vue-touch-id']; 200 | var data = workSpace[key]; 201 | for (var i in data) { 202 | if (data.hasOwnProperty(i) && i) { 203 | Helper.detachEvent(el, data[i].handler); 204 | } 205 | } 206 | delete workSpace[key]; 207 | } 208 | }); 209 | }; 210 | 211 | if ((typeof exports === 'undefined' ? 'undefined' : _typeof(exports)) == "object") { 212 | module.exports = vueTouch; 213 | } else if (typeof define == "function" && define.amd) { 214 | define([], function () { 215 | return vueTouch; 216 | }); 217 | } else if (window.Vue) { 218 | window.vueTouch = vueTouch; 219 | Vue.use(vueTouch); 220 | } 221 | }(); -------------------------------------------------------------------------------- /dist/index.min.js: -------------------------------------------------------------------------------- 1 | "use strict";var _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};!function(){var e={getTimestamp:function(){return(new Date).getTime()},getRandomKey:function(){return"vue-touch-"+(Math.random()+"").replace(/\D/g,"")},getType:function(e,t){var n=null,o=Math.min(2,window.devicePixelRatio),r=t.T-e.T,a=(t.X-e.X)/o,i=(t.Y-e.Y)/o,u=Math.abs(a),c=Math.abs(i),s=Math.sqrt(Math.pow(a,2)+Math.pow(i,2));switch(!0){case r<3:break;case r>500&&s<20:n="long";break;case s<6:n="tap";break;case a>0&&c<35:n="right";break;case a<0&&c<35:n="left";break;case i>0&&c>u:n="down";break;case i<0&&c>u:n="up"}return n},getEventName:function(){return n?{start:"touchstart",end:"touchend"}:{start:"mousedown",end:"mouseup"}},attachEvent:function(t,n,o){var r=e.getEventName();t.addEventListener(r.start,n.start,o),t.addEventListener(r.end,n.end,o)},detachEvent:function(t,n){var o=e.getEventName();t.removeEventListener(o.start,n.start),t.removeEventListener(o.end,n.end)}},t={},n="ontouchstart"in window||navigator.MaxTouchPoints>0||navigator.msMaxTouchPoints>0||/(Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone)/i.test(navigator.userAgent),o=function(e,t,n){return n.stop&&t.stopPropagation(),n.prevent&&t.preventDefault(),!n.self||e===t.target},r=function(t){return{start:function r(a){var u=this["vue-touch-id"],c=i[u][t],s=c.method,d=c.modifiers,r=c.start;return n?(r.X=a.touches[0].pageX,r.Y=a.touches[0].pageY):(r.X=a.screenX,r.Y=a.screenY),r.T=e.getTimestamp(),!!o(this,a,d)&&(c.cycle=1,void("long"===t&&(c.timer&&clearTimeout(c.timer),c.timer=setTimeout(function(){c.cycle<3&&s(a),c.timer=0},300))))},end:function r(u){var r={X:0,Y:0,T:e.getTimestamp()};n?(r.X=u.changedTouches[0].pageX,r.Y=u.changedTouches[0].pageY):(r.X=u.screenX,r.Y=u.screenY);var c=this["vue-touch-id"],s=i[c][t],d=s.method,h=s.modifiers,f=s.start;return s.cycle=3,!(!t||e.getType(f,r)!==t)&&(!!o(this,u,h)&&("long"!==t&&d(u,f,r),h.once&&(e.detachEvent(this,s.handler),delete i[c][t]),void(null!==a&&a(this,t,u))))}}},a=null,i={};t.install=function(t,n){n&&n.afterEvent&&"function"==typeof n.afterEvent&&(a=n.afterEvent),t.directive("touch",{bind:function(t,n){var o=n.arg,a=n.modifiers,u=!!a.capture,c=n.value,s="";if("function"!=typeof n.value||!n.arg)return console.error("[Vue warn]: Invalid parameter, Expected Function.");t.hasOwnProperty("vue-touch-id")?s=t["vue-touch-id"]:(s=t["vue-touch-id"]=e.getRandomKey(),i[s]={});var d=r(o);i[s][o]={method:c,modifiers:a,handler:d,start:{X:0,Y:0,T:0},timer:0,cycle:0},e.attachEvent(t,d,u)},update:function(e,t){var n=t.arg,o=t.value,r=e["vue-touch-id"],a=i[r];a.hasOwnProperty(n)&&(a[n].method=o)},unbind:function(t){var n=t["vue-touch-id"],o=i[n];for(var r in o)o.hasOwnProperty(r)&&r&&e.detachEvent(t,o[r].handler);delete i[n]}})},"object"==("undefined"==typeof exports?"undefined":_typeof(exports))?module.exports=t:"function"==typeof define&&define.amd?define([],function(){return t}):window.Vue&&(window.vueTouch=t,Vue.use(t))}(); -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp'); 2 | const babel = require('gulp-babel'); 3 | const uglify = require('gulp-uglify'); 4 | const rename = require('gulp-rename'); 5 | 6 | gulp.task('default', () => { 7 | return gulp.src('src/index.js') 8 | .pipe(babel({ 9 | presets: ['es2015'] 10 | })) 11 | .pipe(gulp.dest('dist')) 12 | .pipe(uglify()) 13 | .pipe(rename({ extname: '.min.js' })) 14 | .pipe(gulp.dest('dist')); 15 | }); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-directive-touch", 3 | "version": "1.0.28", 4 | "description": "Touch directive of vue 2.0", 5 | "main": "dist/index.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/BensonDu/vue-directive-touch.git" 9 | }, 10 | "keywords": [ 11 | "vue", 12 | "2.0", 13 | "touch", 14 | "mobile", 15 | "v-touch" 16 | ], 17 | "author": "Benson ", 18 | "license": "MIT", 19 | "scripts": { 20 | "build": "gulp" 21 | }, 22 | "devDependencies": { 23 | "babel-preset-es2015": "^6.18.0", 24 | "gulp": "^3.9.1", 25 | "gulp-babel": "^6.1.2", 26 | "gulp-rename": "^1.2.2", 27 | "gulp-uglify": "^2.0.1" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | !function() { 2 | let Helper = { 3 | getTimestamp(){ 4 | return new Date().getTime(); 5 | }, 6 | getRandomKey(){ 7 | return 'vue-touch-' + (Math.random() + '').replace(/\D/g, ''); 8 | }, 9 | getType(start,end){ 10 | let type = null; 11 | let ratio = Math.min(2, window.devicePixelRatio); 12 | let during = end.T - start.T; 13 | let h = (end.X - start.X)/ratio; 14 | let v = (end.Y - start.Y)/ratio; 15 | let absh = Math.abs(h); 16 | let absv = Math.abs(v); 17 | let move = Math.sqrt(Math.pow(h,2) + Math.pow(v,2)); 18 | switch (true){ 19 | case (during < 3): 20 | break; 21 | case (during > 500 && move < 20): 22 | type = 'long'; 23 | break; 24 | case (move < 6): 25 | type = 'tap'; 26 | break; 27 | case (h > 0 && absv < 35): 28 | type = 'right'; 29 | break; 30 | case (h < 0 && absv < 35): 31 | type = 'left'; 32 | break; 33 | case (v > 0 && absv > absh): 34 | type = 'down'; 35 | break; 36 | case (v < 0 && absv > absh): 37 | type = 'up'; 38 | break; 39 | default: 40 | } 41 | return type; 42 | }, 43 | getEventName(){ 44 | return isMobile ? { 45 | start: 'touchstart', 46 | end : 'touchend' 47 | } : { 48 | start : 'mousedown', 49 | end : 'mouseup' 50 | }; 51 | }, 52 | attachEvent(el,handler,capture){ 53 | let event = Helper.getEventName(); 54 | el.addEventListener(event.start,handler.start,capture); 55 | el.addEventListener(event.end,handler.end,capture); 56 | }, 57 | detachEvent(el,handler){ 58 | let event = Helper.getEventName(); 59 | el.removeEventListener(event.start,handler.start); 60 | el.removeEventListener(event.end,handler.end); 61 | } 62 | }; 63 | let vueTouch = {}; 64 | let isMobile = (('ontouchstart' in window) || (navigator.MaxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0)) || /(Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone)/i.test(navigator.userAgent); 65 | let modifierRules = function (dom,e, modifiers) { 66 | /* 禁止冒泡 */ 67 | modifiers.stop && e.stopPropagation(); 68 | /* 阻止默认事件 */ 69 | modifiers.prevent && e.preventDefault(); 70 | /* 元素本身事件 */ 71 | if(modifiers.self && dom !== e.target){ 72 | return false; 73 | } 74 | return true; 75 | }; 76 | let newHandler = function (type) { 77 | return { 78 | start(e){ 79 | let key = this['vue-touch-id']; 80 | let data = workSpace[key][type]; 81 | let method = data.method; 82 | let modifiers = data.modifiers; 83 | let start = data.start; 84 | if(isMobile){ 85 | start.X = e.touches[0].pageX; 86 | start.Y = e.touches[0].pageY; 87 | } 88 | else{ 89 | start.X = e.screenX; 90 | start.Y = e.screenY; 91 | } 92 | start.T = Helper.getTimestamp(); 93 | /* 修饰符策略 */ 94 | if(!modifierRules(this,e,modifiers)){ 95 | return false; 96 | } 97 | /* 周期开始 */ 98 | data.cycle = 1; 99 | /* 长按计时器 */ 100 | if(type === 'long'){ 101 | if(data.timer)clearTimeout(data.timer); 102 | data.timer = setTimeout(function () { 103 | data.cycle < 3 && method(e); 104 | data.timer = 0; 105 | },300); 106 | } 107 | }, 108 | end(e){ 109 | let end = { 110 | X : 0, 111 | Y : 0, 112 | T : Helper.getTimestamp() 113 | }; 114 | if(isMobile){ 115 | end.X = e.changedTouches[0].pageX; 116 | end.Y = e.changedTouches[0].pageY; 117 | } 118 | else{ 119 | end.X = e.screenX; 120 | end.Y = e.screenY; 121 | } 122 | 123 | let key = this['vue-touch-id']; 124 | let data = workSpace[key][type]; 125 | let method = data.method; 126 | let modifiers = data.modifiers; 127 | let start = data.start; 128 | /* 周期完成 */ 129 | data.cycle = 3; 130 | if(!type || Helper.getType(start,end) !== type)return false; 131 | /* 修饰符策略 */ 132 | if(!modifierRules(this,e,modifiers)){ 133 | return false; 134 | } 135 | /* 事件执行 */ 136 | type !== 'long' && method(e, start, end); 137 | /* 单次执行结束后释放事件及数据 */ 138 | if(modifiers.once){ 139 | Helper.detachEvent(this,data.handler); 140 | delete workSpace[key][type]; 141 | } 142 | /* 执行 afterEvent Hook */ 143 | if (afterEvent !== null) { 144 | afterEvent(this,type,e); 145 | } 146 | } 147 | } 148 | }; 149 | let afterEvent = null; 150 | let workSpace = {}; 151 | 152 | vueTouch.install = function(Vue,options) { 153 | if (options && options.afterEvent && typeof options.afterEvent === 'function') afterEvent = options.afterEvent; 154 | Vue.directive('touch',{ 155 | bind(el,binding){ 156 | let type = binding.arg; 157 | let modifiers = binding.modifiers; 158 | let capture = !!modifiers.capture; 159 | let method = binding.value; 160 | let key = ''; 161 | 162 | if(typeof binding.value !== 'function' || !binding.arg){ 163 | return console.error('[Vue warn]: Invalid parameter, Expected Function.'); 164 | } 165 | 166 | if(el.hasOwnProperty('vue-touch-id')){ 167 | key = el['vue-touch-id']; 168 | } 169 | else{ 170 | key = el['vue-touch-id'] = Helper.getRandomKey(); 171 | workSpace[key] = {}; 172 | } 173 | let handler = newHandler(type); 174 | workSpace[key][type] = { 175 | method, 176 | modifiers, 177 | handler, 178 | start : { 179 | X : 0, 180 | Y : 0 , 181 | T : 0 182 | }, 183 | timer : 0, 184 | cycle : 0 185 | }; 186 | Helper.attachEvent(el,handler,capture); 187 | }, 188 | update(el,binding){ 189 | let type = binding.arg; 190 | let method = binding.value; 191 | let key = el['vue-touch-id']; 192 | let data = workSpace[key]; 193 | if(data.hasOwnProperty(type)){ 194 | data[type].method = method; 195 | } 196 | }, 197 | unbind(el){ 198 | let key = el['vue-touch-id']; 199 | let data = workSpace[key]; 200 | for(let i in data){ 201 | if(data.hasOwnProperty(i) && i){ 202 | Helper.detachEvent(el,data[i].handler); 203 | } 204 | } 205 | delete workSpace[key]; 206 | } 207 | }); 208 | }; 209 | 210 | if (typeof exports == "object") { 211 | module.exports = vueTouch; 212 | } 213 | else if (typeof define == "function" && define.amd) { 214 | define([], function(){ return vueTouch }) 215 | } 216 | else if (window.Vue) { 217 | window.vueTouch = vueTouch; 218 | Vue.use(vueTouch); 219 | } 220 | }(); 221 | --------------------------------------------------------------------------------