在手持設備上使用 touchstart 事件代替 click 事件是不是個好主意?

GitHub 上有一個項目叫 ftlabs/fastclick · GitHub ,對於解決此問題是否有幫助?


在手持設備的瀏覽器上(本處主要指代iOS和Android系統上的webkit內核的瀏覽器和嵌入在應用程序裡面的webview),由於兩次連續「輕觸」是「放大」的操作(即使你兩次輕觸的是一個鏈接或一個有click事件監聽器的元素),所以在第一次被「輕觸」後,瀏覽器需要先等一段時間,看看有沒有所謂的「連續的第二次輕觸」。如果有,則進行「放大」操作。沒有,才敢放心地認為用戶不是要放大,而是需要「click」至此才敢觸發click事件,導致「短按(手指接觸屏幕到離開屏幕的時間比較短)」的click事件通常約會延遲300ms左右。

採用touchstart代替click是比較初級的解決方案,首先,touchstart和click的觸發條件就有區別,對於手持設備的瀏覽器:

1.touchstart:在這個dom(或冒泡到這個dom,這當然是廢話)上手指觸摸開始即能觸發

2.click:在這個dom(或冒泡到這個dom,這當然是廢話)上手指觸摸開始,且手指未曾在屏幕上移動(某些瀏覽器允許移動一個非常小的位移值),且在這個在這個dom上手指離開屏幕,且觸摸和離開屏幕之間的間隔時間較短(某些瀏覽器不檢測間隔時間,也會觸發click)才能觸發

於是我們可以看到,完全用touchstart代替是不太可取的。

根據上面的區別,又要規避click在移動手持設備上帶來的延遲,很容易有了模擬的辦法,大致思路是:

在touchstart、touchend時記錄時間、手指位置,在touchend時進行比較,如果手指位置為同一位置(或允許移動一個非常小的位移值)且時間間隔較短(一般認為是200ms),且過程中未曾觸發過touchmove,即可認為觸發了手持設備上的「click」,一般稱它為「tap」

zepto已經封裝了上述tap:zepto/src/touch.js at master 路 madrobby/zepto 路 GitHub

另外(由下面的@張辰 同學的回答,)還可以直接使用Fastclick:ftlabs/fastclick · GitHub來模擬點擊,也不會有延遲,目前我已經遷移到此方案。

更新:

  • zepto先前的實現方案有一些小問題,某些情況下會導致點透(http://blog.youyo.name/archives/zepto-tap-click-through-research.html),現在最新版的已經修復了這個問題。

  • 在安卓4.1+的chrome瀏覽器上,如果在meta viewport中指定頁面不可縮放,則click沒有上述300ms左右的延遲


非常占同 @悠悠 的回答,理論部分已經回答得相當好,我來點實踐內容。

如下面這個場景,在頁面底部有一個「回頂部」的按鈕,當我點擊時,觸發函數:

window.scrollTo(0, 1);

剛開始我使用 touchend 替代 click,當觸發 scrollTo 的同時,頁面發生了跳轉,開始我感到非常奇怪,為什麼頁面會跳轉呢?

最後,確認問題 scrollTo 動作是在 touchend 時觸發,此時,並未觸發click,在滾動回頁面頂部時,click被觸發,誤中頁面頂部的一個鏈接,導致頁面發生跳轉。

事件觸發順序:touchend --&> scrollTo(0, 1) --&> click --&> 點中頁面頂部的鏈接跳轉

在大部分情況下,還是可以直接使用 touchend 替代,但是一定要如 @悠悠 答案中所說:

在touchstart、touchend時記錄時間、手指位置,在touchend時進行比較,如果手指位置為同一位置(或允許移動一個非常小的位移值)且時間間隔較短(一般認為是200ms),且過程中未曾觸發過touchmove,即可認為觸發了手持設備上的「click」,一般稱它為「tap」

Note:這個問題不是所有手機都會發生,目前,只在魅族MX2自帶瀏覽器被驗證,下面的截圖是使用三星i9100示意。


先佔個坑。

光touchstart本身不能完全替代click。解決方案見fastclick庫。

其他庫如hammer等雖然支持tap手勢,但是單純支持tap就喪失了web應有的設備無關性。而fastclick雖然解決了click問題,但是不支持其他手勢,實用性不夠。

我正在開發一個新的手勢庫 https://github.com/hax/zhi 來解決上述問題。目前還是alpha版本。


Touch start 相當於on mouse down 吧


TOUCHSTART不能代替click,大家都知道了。既然提到了fast click,我再補充一下心得。首先,這個插件非常方便,只需調用一次即可;第二,在iPhone和BB10上,表現是完美的;第三,如果你用在Android APK包裡面的Web View上,會產生用戶本來只想滑動卻誤點的Bug,因為Android機器性能就參差不齊,而且APK包自帶的那個瀏覽器很渣。所以如果使用FastClick,最好做個判斷,不要用在Android APK裡面。


看你的產品操作形式而定,,,不必從定義和原理上深究,該變通就變通


前面的 @悠悠 同學已經說得很明白了,補充下有個獨立的庫也可以解決這個問題:FT Fast Click https://github.com/ftlabs/fastclick


很顯然不是...從名字上看就不是一個意思...


基本沒法用

在安卓2.x上touchstart隨機不觸發 而且touchstart touchmove touchend 和click mousemove等事件的順序也是隨機的

沒記錯的話4.0.x上也有隨機不觸發的現象


是個好主意,反應速度會快很多。


推薦閱讀:

PHP 和 node.js 共存的問題?
英文不好可以看關於JS的英文原版書嗎?
用HTML5 canvas做數學公式手寫識別需要多大的工作量?
網站的後台技術人員是如何反制搶票軟體的?
Chrome 對 JS 的支持似乎不是很好,為什麼有些 JS 腳本執行不了?要怎麼解決這個問題?

TAG:前端開發 | JavaScript |