快速反饋對於任何 UI 的實現都是相當重要的。研究代表,100ms 是界面讓用戶感到即時的最大延遲。儘管如此,移動網絡仍然受到一個巨大的反饋問題的困擾:觸摸任何元素後,延遲 300 毫秒。這種延遲是許多用戶認爲基於 HTML 的 Web 應用程序「卡頓」的最重要緣由之一。在本文中,本文將帶你瞭解移動端點擊事件延遲的從誕生到消亡的過程。css
在 2007 年,蘋果公司發佈首款 iPhone 以前,因爲當時的網站廣泛爲大屏幕設備所設計,爲了應對 iPhone 這種小屏幕設備瀏覽桌面網站的問題,由此,蘋果引入了多項變革,其中就包含了「雙擊縮放準肯定位正文主體,並將其縮放至適合的比例展示」的功能,即雙擊縮放功能。然而,因爲這種雙擊縮放的操做,在用戶第一次單擊頁面元素時,瀏覽器並不知道用戶是想作雙擊縮放操做仍是普通的單擊操做。所以,IOS Safari 瀏覽器首先引入了 300 毫秒延遲,用來判斷用戶是否會再次點擊,也就是說,在第一次點擊延遲 300 毫秒,300 毫秒後用戶沒有再次點擊則認定爲用戶在進行普通的單擊操做,並觸發單擊(Click)事件。html
全面的移動開發者與單擊事件延遲戰爭拉開了序幕。鑑於 iPhone 的巨大成功,其餘瀏覽器廠商也都快步跟進紛紛效仿了 iPhone Safari 瀏覽器的作法。因而,單擊事件延遲成爲了移動開發者不得不面對的痛。git
雖然從當時來看 300ms 延遲並無什麼不妥,然而在愈來愈注重用戶體驗的移動互聯網時代,這種延遲是沒法被用戶所接受的,加之開發者也能夠對網站進行響應式適配,雙擊縮放的操做變成了一種無關緊要的操做,瀏覽器廠商開始意識到延遲所帶來的體驗問題,提出了一些解決方案。github
解決此問題的第一個方法是常識性方法。因爲延遲產生的緣由是雙擊縮放操做,那麼就禁用頁面縮放功能,最直接的方法就是設置 Viewport 禁止縮放,代碼以下:瀏覽器
<meta name="viewport" content="user-scalable=no"> <!-- 或者 --> <meta name="viewport" content="initial-scale=1,maximum-scale=1">
適用於 Android 的 Chrome 瀏覽器是第一個引入此更改的應用程序,隨後緊接着是 Android 的 Firefox。沒有其餘瀏覽器供應商宣佈要添加此優化的計劃。儘管此解決方案很是巧妙,背後卻以犧牲整個頁面縮放爲代價,帶來的影響是對於頁面上的圖像或小文本,想要進行縮放變得難以完成。即大多數網站都沒法從 Android 版 Chrome 和 Android 版 Firefox 的優化中受益。網絡
幸運的是,隨後 Chrome 團隊在 Chrome 32 以後的版本中,提出了新的優秀方案,代碼以下:優化
<meta name="viewport" content="width=device-width">
約定當 Viewport 的 width 小於或等於 device-width 時,去除雙擊縮放功能。這項技術的另外一個關鍵在於,它僅消除了雙擊縮放的功能,用戶依然可使用雙指縮放功能。所以,不存在與禁用縮放相關的可用性和可訪問性問題。網站
指針事件是 Microsoft 提出的一系列針對 Web 的新事件,現已成爲 W3C 規範。指針事件規範是嘗試使用單個事件模型統一咱們對全部輸入類型(鼠標,觸摸,手寫筆等)的處理。根據規範,CSS 屬性 touch-action 用於設置觸摸屏用戶如何操縱元素的區域(例如,瀏覽器內置的縮放功能)。touch-action 默認值是 auto,當設置爲 none 時會禁止用戶縮放,能成功解決 300ms 延遲的問題,如:spa
a[href], button { touch-action: none; }
甚至能夠添加 touch-action: none 到 body 以徹底禁用雙擊來縮放(注意:這也將禁用雙指縮放功能,所以它與咱們前面討論的與禁用縮放相關的可訪問性和可用性問題相同)。scala
2014年3月13日,W3C 規範增添了新的 touch-action 屬性值 manipulation。該屬性值提供了一箭雙鵰的體驗;它容許雙指縮放,以免 touch-action: none 出現的可訪問性和可用性問題,但它仍然能夠經過禁用雙擊縮放來消除 300ms 的延遲。
FastClick 是一個小型 JavaScript 庫,專門旨在防止移動瀏覽器中的 300ms 點擊延遲。FastClick 的實現基礎創建於 touchstart ,touchmove 或者 touchend 事件中的任意一個調用 event.preventDefault,mouse 事件 以及 click 事件將不會觸發。FastClick 的原理在 touchend 階段調用 event.preventDefault,而後經過 document.createEvent 建立一個自定義事件 MouseEvents,而後經過 eventTarget.dispatchEvent 觸發對應目標元素上綁定的 click 事件。
關於 FastClick 的好處是,它很是容易使用,只需在文檔加載後調用 FastClick.attach() 在 body 元素上實例化:
if ('addEventListener' in document) { document.addEventListener('DOMContentLoaded', function() { FastClick.attach(document.body); }, false); }
FastClick足夠聰明,能夠檢測到若是是桌面瀏覽器或者存在 meta 標記和 touch-action 解決方案的時候,不會執行任何操做。所以,在咱們爲全部平臺提供真正的解決方案以前,這是一個極好的解決方法。
得益於現代瀏覽器對 W3C 規範 touch-action: manipulation 的支持性,才真正完全解決了點擊事件延遲的問題。touch-action: manipulation 規定瀏覽器只容許進行滾動和持續縮放操做。任何其它被 touch-action: auto 支持的行爲不被支持。啓用平移和雙指縮放手勢,但禁用其餘非標準手勢,例如雙擊縮放。 禁用雙擊縮放功能可減小瀏覽器在用戶點擊屏幕時延遲生成點擊事件的須要。代碼以下:
html { touch-action: manipulation; }
今後,移動端點擊事件延遲正式宣告消亡。