vue-tap.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /**
  2. * Created by 二哲 on 15/12/6.
  3. */
  4. /*
  5. * 不带参数指令
  6. * v-tap=handler
  7. * or
  8. * 带参数指令
  9. * v-tap=handler($index,el,$event)
  10. *
  11. * !!!新增!!!
  12. * 把tapObj对象注册在原生event对象上
  13. * event.tapObj拥有6个值
  14. * pageX,pageY,clientX,clientY,distanceX,distanceY
  15. * 后面2个分别的手指可能移动的位置(以后可用于拓展手势)
  16. *
  17. * */
  18. ;(function () {
  19. var vueTap = {};
  20. var isVue2 = false;
  21. /** 公用方法开始 **/
  22. function isPc() {
  23. var uaInfo = navigator.userAgent;
  24. var agents = ["Android", "iPhone", "Windows Phone", "iPad", "iPod"];
  25. var flag = true;
  26. for ( var i = 0; i < agents.length; i++ ) {
  27. if (uaInfo.indexOf(agents[i]) > 0) {
  28. flag = false;
  29. break;
  30. }
  31. }
  32. return flag;
  33. }
  34. function isTap(self) {
  35. if (isVue2 ? self.disabled : self.el.disabled) {
  36. return false;
  37. }
  38. var tapObj = self.tapObj;
  39. return self.time < 300 && Math.abs(tapObj.distanceX) < 10 && Math.abs(tapObj.distanceY) < 10;
  40. }
  41. function touchstart(e, self) {
  42. var touches = e.touches[0];
  43. var tapObj = self.tapObj;
  44. tapObj.pageX = touches.pageX;
  45. tapObj.pageY = touches.pageY;
  46. tapObj.clientX = touches.clientX;
  47. tapObj.clientY = touches.clientY;
  48. self.time = +new Date();
  49. }
  50. function touchend(e, self) {
  51. var touches = e.changedTouches[0];
  52. var tapObj = self.tapObj;
  53. self.time = +new Date() - self.time;
  54. tapObj.distanceX = tapObj.pageX - touches.pageX;
  55. tapObj.distanceY = tapObj.pageY - touches.pageY;
  56. if (!isTap(self)) return;
  57. self.handler(e);
  58. }
  59. /** 公用方法结束 * */
  60. var vue1 = {
  61. isFn: true,
  62. acceptStatement: true,
  63. update: function (fn) {
  64. var self = this;
  65. self.tapObj = {};
  66. if (typeof fn !== 'function' && self.el.tagName.toLocaleLowerCase() !== 'a') {
  67. return console.error('The param of directive "v-tap" must be a function!');
  68. }
  69. self.handler = function (e) { //This directive.handler
  70. e.tapObj = self.tapObj;
  71. if (self.el.href && !self.modifiers.prevent) {
  72. return window.location = self.el.href;
  73. }
  74. var tagName = e.target.tagName.toLocaleLowerCase();
  75. if(tagName === 'input' || tagName === 'textarea') {
  76. return e.target.focus();
  77. }
  78. fn.call(self, e);
  79. };
  80. if (isPc()) {
  81. self.el.addEventListener('click', function (e) {
  82. if (self.el.href && !self.modifiers.prevent) {
  83. return window.location = self.el.href;
  84. }
  85. self.handler.call(self, e);
  86. }, false);
  87. } else {
  88. self.el.addEventListener('touchstart', function (e) {
  89. if (self.modifiers.stop)
  90. e.stopPropagation();
  91. if (self.modifiers.prevent)
  92. e.preventDefault();
  93. touchstart(e, self);
  94. }, false);
  95. self.el.addEventListener('touchend', function (e) {
  96. try {
  97. Object.defineProperty(e, 'currentTarget', {// 重写currentTarget对象 与jq相同
  98. value: self.el,
  99. writable: true,
  100. enumerable: true,
  101. configurable: true
  102. })
  103. } catch (e) {
  104. // ios 7下对 e.currentTarget 用defineProperty会报错。
  105. // 报“TypeError:Attempting to configurable attribute of unconfigurable property”错误
  106. // 在catch里重写
  107. console.error(e.message)
  108. e.currentTarget = self.el
  109. }
  110. e.preventDefault();
  111. return touchend(e, self);
  112. }, false);
  113. }
  114. }
  115. };
  116. var vue2 = {
  117. bind: function (el, binding) {
  118. el.tapObj = {};
  119. el.handler = function (e,isPc) { //This directive.handler
  120. var value = binding.value;
  121. if (!value && el.href && !binding.modifiers.prevent) {
  122. return window.location = el.href;
  123. }
  124. value.event = e;
  125. var tagName = value.event.target.tagName.toLocaleLowerCase();
  126. !isPc ? value.tapObj = el.tapObj : null;
  127. if(tagName === 'input' || tagName === 'textarea') {
  128. return value.event.target.focus();
  129. }
  130. value.methods.call(this, value);
  131. };
  132. if (isPc()) {
  133. el.addEventListener('click', function (e) {
  134. if (binding.modifiers.stop)
  135. e.stopPropagation();
  136. if (binding.modifiers.prevent)
  137. e.preventDefault();
  138. el.handler(e, true)
  139. }, false);
  140. } else {
  141. el.addEventListener('touchstart', function (e) {
  142. if (binding.modifiers.stop)
  143. e.stopPropagation();
  144. if (binding.modifiers.prevent)
  145. e.preventDefault();
  146. touchstart(e, el);
  147. }, false);
  148. el.addEventListener('touchend', function (e) {
  149. try {
  150. Object.defineProperty(e, 'currentTarget', {// 重写currentTarget对象 与jq相同
  151. value: el,
  152. writable: true,
  153. enumerable: true,
  154. configurable: true
  155. })
  156. } catch (e) {
  157. // ios 7下对 e.currentTarget 用defineProperty会报错。
  158. // 报“TypeError:Attempting to configurable attribute of unconfigurable property”错误
  159. // 在catch里重写
  160. console.error(e.message)
  161. e.currentTarget = el
  162. }
  163. e.preventDefault();
  164. return touchend(e, el);
  165. }, false);
  166. }
  167. },
  168. componentUpdated : function(el,binding) {
  169. el.tapObj = {};
  170. el.handler = function (e,isPc) { //This directive.handler
  171. var value = binding.value;
  172. if (!value && el.href && !binding.modifiers.prevent) {
  173. return window.location = el.href;
  174. }
  175. value.event = e;
  176. !isPc ? value.tapObj = el.tapObj : null;
  177. value.methods.call(this, value);
  178. };
  179. },
  180. unbind: function (el) {
  181. // 卸载,别说了都是泪
  182. el.handler = function () {};
  183. }
  184. };
  185. vueTap.install = function (Vue) {
  186. if (Vue.version.substr(0, 1) > 1) {
  187. isVue2 = true;
  188. }
  189. Vue.directive('tap', isVue2 ? vue2 : vue1);
  190. };
  191. vueTap.version = '3.0.3';
  192. if (typeof exports == "object") {
  193. module.exports = vueTap;
  194. } else if (typeof define == "function" && define.amd) {
  195. define([], function () {
  196. return vueTap
  197. })
  198. } else if (window.Vue) {
  199. window.vueTap = vueTap;
  200. Vue.use(vueTap);
  201. }
  202. })();