共 1 条评论关于"关于zepto.js中tap事件会触发两次问题"
最新评论
绝大多数朋友做移动端会考虑到使用zepto.js,其原因不言而喻,小巧玲珑,用法和jQuery大同小异,但这玩意儿第一次用,还是有点坑的
原因是:这个傻逼zepto.js把最重要的touch事件单独剥离出来了,也就是说你需要单独在zepto.js后面再引用touch.js才行,在官方Github里下载整个项目,具体位置如下图所示:
看到木有,是不是傻逼,说他傻逼绝对错不了,仅仅5.9kb,但这个傻逼非要剥离 剥离出来了,然后很多新人找到zepto.js就赶紧用,然后死不执行!
最新版Chrome绑定了三个事件touchend MSPointerUp pointerup,touchend是触摸相关的事件,MSPointerUp 是ie10的触摸事件,pointerup是指针事件。
可能是以前的chrome不支持pointerup事件,现在新版本支持了,然后会报错了,把zepto里面pointerup相关的事件都删除了后测试没有问题。
zepto目前还没修复,不过issue已经列出来了。
现在问题来了,在zepto中tap执行速度最快,但在某些设备上执行两次,singleTap其次,延迟了250毫秒,click无疑是最慢的(延迟了300毫秒),可能你会说我怎么知道singleTap延迟的是250毫秒?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | .on('touchstart MSPointerDown pointerdown', function(e){ if((_isPointerType = isPointerEventType(e, 'down')) && !isPrimaryTouch(e)) return firstTouch = _isPointerType ? e : e.touches[0] if (e.touches && e.touches.length === 1 && touch.x2) { // Clear out touch movement data if we have it sticking around // This can occur if touchcancel doesn't fire due to preventDefault, etc. touch.x2 = undefined touch.y2 = undefined } now = Date.now() delta = now - (touch.last || now) touch.el = $('tagName' in firstTouch.target ? firstTouch.target : firstTouch.target.parentNode) touchTimeout && clearTimeout(touchTimeout) touch.x1 = firstTouch.pageX touch.y1 = firstTouch.pageY if (delta > 0 && delta <= 250) touch.isDoubleTap = true touch.last = now longTapTimeout = setTimeout(longTap, longTapDelay) // adds the current touch contact for IE gesture recognition if (gesture && _isPointerType) gesture.addPointer(e.pointerId) }) .on('touchmove MSPointerMove pointermove', function(e){ if((_isPointerType = isPointerEventType(e, 'move')) && !isPrimaryTouch(e)) return firstTouch = _isPointerType ? e : e.touches[0] cancelLongTap() touch.x2 = firstTouch.pageX touch.y2 = firstTouch.pageY deltaX += Math.abs(touch.x1 - touch.x2) deltaY += Math.abs(touch.y1 - touch.y2) }) .on('touchend MSPointerUp pointerup', function(e){ if((_isPointerType = isPointerEventType(e, 'up')) && !isPrimaryTouch(e)) return cancelLongTap() // swipe if ((touch.x2 && Math.abs(touch.x1 - touch.x2) > 30) || (touch.y2 && Math.abs(touch.y1 - touch.y2) > 30)) swipeTimeout = setTimeout(function() { if (touch.el){ touch.el.trigger('swipe') touch.el.trigger('swipe' + (swipeDirection(touch.x1, touch.x2, touch.y1, touch.y2))) } touch = {} }, 0) // normal tap else if ('last' in touch) // don't fire tap when delta position changed by more than 30 pixels, // for instance when moving to a point and back to origin if (deltaX < 30 && deltaY < 30) { // delay by one tick so we can cancel the 'tap' event if 'scroll' fires // ('tap' fires before 'scroll') tapTimeout = setTimeout(function() { // trigger universal 'tap' with the option to cancelTouch() // (cancelTouch cancels processing of single vs double taps for faster 'tap' response) var event = $.Event('tap') event.cancelTouch = cancelAll // [by paper] fix -> "TypeError: 'undefined' is not an object (evaluating 'touch.el.trigger'), when double tap if (touch.el) touch.el.trigger(event) // trigger double tap immediately if (touch.isDoubleTap) { if (touch.el) touch.el.trigger('doubleTap') touch = {} } // trigger single tap after 250ms of inactivity else { touchTimeout = setTimeout(function(){ touchTimeout = null if (touch.el) touch.el.trigger('singleTap') touch = {} }, 250) } }, 0) } else { touch = {} } deltaX = deltaY = 0 }) |
从touch.js源代码143行(未压缩版)可以看到,singleTap事件被用定时器延迟了250毫秒,可能是防止tap事件出现的“点透”问题,关于“tap”点透自行百度。只需要把250改成0即可取消singleTap的延迟,也不会执行2次
首先说下为什么会延迟,从点击屏幕上的元素到触发元素的 click 事件,移动浏览器会有大约 300 毫秒的等待时间。为什么这么设计呢? 因为它想看看你是不是要进行双击(double tap)操作。
其实zpeto.js我并不喜欢,一个个模块引用起来太麻烦了,功能还不如jQuery,bug多的一逼,如果你只是想解决移动端延迟问题,可以选择fastclick.js,地址:fastclick.js官方下载
使用方法:
必须在页面所有Element之前加载脚本文件先实例化fastclick,在JS中添加fastclick的身体,推荐以下做法(值得一提的是fastclick.js并非需要基于jQuery)
1 2 3 4 5 | if ('addEventListener' in document) { document.addEventListener('DOMContentLoaded', function() { FastClick.attach(document.body); }, false); } |
如果你使用了JQuery,那么JS引入就可以改用下面的写法:
1 2 3 | $(function() { FastClick.attach(document.body); }); |
后面你用click事件就已经没有延迟问题了
注:恨死博客园、CSDN博客还有什么简书,一堆IT技术界垃圾,一篇文章不论对错到处复制粘贴,甚至我在找这个问题答案时候,看到有的文章结尾扬言,想知道怎么解决?请联系我QQ:xx,艹
上一篇:高质量免费虚拟主机 – 景安网络-国内专业的虚拟主机
最新评论
支付宝扫一扫打赏
微信扫一扫打赏
厉害了