之前翻譯過一篇關於fastclick的快速點擊文章http://www.cnblogs.com/lilyimage/p/3568773.html,fastclick可以解決在手機上點擊事件的300ms延遲;另外我們也知道zepto的touch模塊,幫助我們實現了很多手機上的事件,比如tap等,tap事件也是為了解決在click的延遲問題。那么他們有什么區別呢?
先看zepto的touch模塊實現:
1 $(document) 2 .on('touchstart ...',function(e){ 3 ... 4 ... 5 now = Date.now() 6 delta = now - (touch.last || now) 7 if (delta > 0 && delta <= 250) touch.isDoubleTap = true 8 touch.last = now 9 }) 10 .on('touchmove ...', function(e){ 11 }) 12 .on('touchend ...', function(e){ 13 ... 14 if (deltaX < 30 && deltaY < 30) { 15 var event = $.Event('tap') 16 17 touch.el.trigger(event) 18 } 19 })
touch模塊綁定事件touchstart,touchmove和touchend到document上,然后通過計算touch事件觸發的時間差,位置差來實現了自定義的tap,swipe等。
那么tap事件為什么會“穿透”呢?
比如下面的代碼:
<html> <head> <meta charset="UTF-8"> <script type="text/javascript" src="/resources/js/zepto.js"></script> <script type="text/javascript" src="/resources/js/zepto-touch.js"></script> <title></title> </head> <body> <style> .q{width: 200px;height: 200px;background-color: red;position: absolute;top:0;;left: 0} .b{width: 300px;height: 300px;background-color: green;position: absolute;top:0;;left: 0} </style> <div class="b"></div> <div class="q"></div> <script> $('.q').on('tap',function(e){ $(this).hide(); }); $('.b').on('click',function(e){ alert("bb"); }); </script> </body> </html>
在手機上,點擊了q以后,就會彈出bb的彈框,為什么呢?
因為tap事件是通過document綁定了touchstart和touchend事件實現,$('.q')上,當touchend事件冒泡到document上以后執行$(this).hide();此時$('.b'),就處在了頁面的最前面,
現在touchend冒泡到了document上,並且$('.b')在頁面的最前面,然后就觸發了click事件。
關於click事件300ms延遲的由來,以及隨着時間的發展,遇到的問題,各家瀏覽器的解決方法和現在的各種js的方法,可以見http://blogs.telerik.com/appbuilder/posts/13-11-21/what-exactly-is.....-the-300ms-click-delay 准備翻譯下。因為里面也介紹了fastclick,呵呵。
今天看到了別人的翻譯稿,拿過來啦,http://thx.github.io/mobile/300ms-click-delay/
所以zepto的touch模塊真的不是一個好的模塊。。不過比我自己寫的好,關鍵是為什么一直都不解決這個點透的問題啊。。
fastclick呢?
它的實際原理是在目標元素上綁定touchstart ,touchend事件,然后在touchend結束的時候立馬執行click事件,這樣就解決了“點透”的問題(實質是事件冒泡導致)以及300ms延遲問題,300ms延遲是因為瀏覽器為了實現用戶雙擊屏幕放大頁面(double tap to zoom 詳細見我下一篇翻譯吧)的效果。
FastClick.prototype.sendClick = function(targetElement, event) { 'use strict'; var clickEvent, touch; // On some Android devices activeElement needs to be blurred otherwise the synthetic click will have no effect (#24) if (document.activeElement && document.activeElement !== targetElement) { document.activeElement.blur(); } touch = event.changedTouches[0]; // 這里就是關鍵,就是在這里實現了click事件 clickEvent = document.createEvent('MouseEvents'); clickEvent.initMouseEvent(this.determineEventType(targetElement), true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null); clickEvent.forwardedTouchEvent = true; targetElement.dispatchEvent(clickEvent); };
在touchEnd的時候會立馬調用這個sendClick
FastClick.prototype.onTouchEnd = function(event){ ...... this.sendClick(targetElement, event); }
好了,這兩個就是這樣了。