移動端300ms延遲
阿新 • • 發佈:2020-08-29
1. 300ms延遲的產生緣由
移動端瀏覽器的預設顯示寬度是980px
(不同機型各異,但相差不大),而不是螢幕的寬度(320px
或其他)。為了對早期普通網頁更好的體驗,iphone
設計了雙擊放大顯示的功能--這就是300ms
延遲的來源:如果使用者一次點選後300ms
內沒有其他操作,則認為是個單擊行為;否則為雙擊放大行為。
2. 點透行為
假設有兩個層級,A
和B
;A
在上面,B
在下面。 如果A
監聽touch
事件(zepto
的tap
事件),而且B
上有個連結(或者監聽click
事件),那麼當touch A
後,先後觸發了touchStart
和touchEnd
事件,touchEnd
後A
層隱藏,而此刻會觸發在document
B
的click
事件;這就是點透行為。
3. 解決方法
- 設定不能縮放:
user-scalable=no
。 不能縮放就不會有雙擊縮放操作,因此click
事件也就沒了300ms
延遲,這個是Chrome
首先在Android
中提出的。 - 設定顯示寬度:
width=device-width
。Chrome
開發團隊不久前宣佈,在Chrome 32
這一版中,他們將在包含 width=device-width 或者置為比 viewport 值更小的頁面上禁用雙擊縮放。當然,沒有雙擊縮放就沒有300
毫秒點選延遲。 IE
的指標事件 (Pointer Events
):設定touch-action:none
,根據touch-action
屬性決定 “是否觸控操作會觸發使用者代理的預設行為。這包括但不限於雙指縮放等行為”。
從實際應用的角度來看,touch-action
決定了使用者在點選了目標元素之後,是否能夠進行雙指縮放或者雙擊縮放。因此,這也相當完美地解決了300
毫秒點選延遲的問題。
鑑於上述的3
種解決方案,現在較為通用的meta
設定為:
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
4. 現在的流行解決方案:
上述的3
種解決方案可以解決Chrome Android
和IE10+
下的300ms
問題,但是對其他瀏覽器還需要特定的解決方案。
- 指標事件的
polyfill
指標事件的polyfill
比較多,以下列出比較流行的幾個。Google
的 Polymer,微軟的 HandJS和@Rich-Harris 的 Points - FastClick
FastClick 是 FT Labs 專門為解決移動端瀏覽器300
毫秒點選延遲問題所開發的一個輕量級的庫。簡而言之,FastClick
在檢測到touchend
事件的時候,會通過 DOM 自定義事件立即觸發一個模擬click
事件,並把瀏覽器在300
毫秒之後真正觸發的click
事件阻止掉。
5. FastClick
現階段FastClick
被更多使用,藉助它通過監聽click
事件,即可消除300ms
的問題。
通過閱讀原始碼可知:
FastClick
通過判斷瀏覽器型別決定其是不是需要執行,下面幾種場景下不會執行FastClick
邏輯:
- 不支援
ontouchstart
事件的瀏覽器 Android Chrome
或者firefox27
以上 設定了user-scalable="no"
- 滿足特定要求的
IE10+
瀏覽器 - 部分黑莓瀏覽器
- 註冊了
touchStart
、touchEnd
等事件,監聽touchStart
決定事件物件的target
、時間、位置等資訊;通過touchEnd
得到touch
的結束時間。如果touch
時長大於700ms
,則是長按事件;如果連續兩次touchEnd
的時間間隔小於200ms
,那麼認定為快速點選,特殊對待;排除上面兩種情況,就通過clickEvent = document.createEvent('MouseEvents'); initMouseEvent; dispatchEvent
手動觸發click
事件。