移動端300ms延遲和點擊穿透

一、移動端點擊產生300 ms的延遲

300ms延遲是指當我們點擊頁面的時候移動端瀏覽器並不是立即作出反應,而是會等上300ms纔會出現點擊的效果。

而設置這300ms的意義在於判斷用戶的雙擊行爲。移動端瀏覽器會有一些默認的行爲,比如雙擊縮放、雙擊滾動。這些行爲,尤其是雙擊縮放,主要是爲桌面網站在移動端的瀏覽體驗設計的。

在移動web的興起初期,人們對這個問題的感知並不明顯,但隨着用戶對交互體驗的要求越來越高,現今,移動端300ms的點擊延遲逐漸變得明顯而無法忍受。

解決方案

目前,瀏覽器開發商的解決方案主要有一下三種方案:

方案一:禁用縮放(HTML文檔頭部設置meta標籤)

<meta name="viewport" content="user-scalable=no">
<meta name="viewport" content="initial-scale=1,maximum-scale=1">

這種方法的缺點顯而易見,我們犧牲了縮放的功能。但實際需求中,我們還是希望能通過雙指還實現縮放的。我們不想要的只是雙擊縮放行爲。

方案二:更改默認的視口寬度

設置視口寬度爲設備寬度:

<meta name="viewport" content="width=device-width">

如果設置了上述meta標籤,那瀏覽器就可以認爲該網站已經對移動端做過了適配和優化,就無需雙擊縮放操作了。
這個方案相比方案一的好處在於,它沒有完全禁用縮放,而只是禁用了瀏覽器默認的雙擊縮放行爲,但用戶仍然可以通過雙指縮放操作來縮放頁面。

方案三:CSS touch-action

CSS屬性touch-action用於設置觸摸屏用戶如何操縱元素的區域(例如,瀏覽器內置的縮放功能)。

如果將該屬性值設置爲touch-action: none,那麼表示在該元素上的操作不會觸發用戶代理的任何默認行爲,就無需進行300ms的延遲判斷。

由於除了IE之外的大部分瀏覽器都不支持這個新的CSS屬性,所以指針事件的polyfill必須通過某種方式去模擬支持這個屬性。一種方案是JS去請求解析所有的樣式表,另一種方案是將touch-action作爲html標籤的屬性。

Polyfill 是一塊代碼(通常是 Web 上的 JavaScript),用來爲舊瀏覽器提供它沒有原生支持的較新的功能。

方案四:FastClick

FastClick 是 FT Labs 專門爲解決移動端瀏覽器 300 毫秒點擊延遲問題所開發的一個輕量級的庫。

FastClick的實現原理是在檢測到touchend事件的時候,會通過DOM自定義事件立即出發模擬一個click事件,並把瀏覽器在300ms之後的click事件阻止掉。

//引入fastclick
<script src="js/fastclick.min.js"></script>

// 原生js初始化
if ('addEventListener' in document) {
    document.addEventListener('DOMContentLoaded', function() {
        FastClick.attach(document.body);
    }, false);
}

方案五:使用touchstart替代click

可能有人會想,既然click點擊有300ms的延遲,那對於觸摸屏,我們直接監聽touchstart事件不就好了嗎?

事實上,使用touchstart去代替click事件有兩個不好的地方。

第一:touchstart是手指觸摸屏幕就觸發,有時候用戶只是想滑動屏幕,卻觸發了touchstart事件,這不是我們想要的結果;

第二:使用touchstart事件在某些場景下可能會出現點擊穿透的現象。下面講一講點擊穿透。

二、點擊穿透

什麼是點擊穿透,點擊穿透爲什麼會發生

假如頁面上有兩個元素A和B。B元素在A元素之上。我們在B元素的touchstart事件上註冊了一個回調函數,該回調函數的作用是隱藏B元素。我們發現,當我們點擊B元素,B元素被隱藏了,隨後,A元素觸發了click事件。當然前提是A元素上綁定了click事件,或者說,A元素是個鏈接<a>、輸入框<input>等。

這是因爲在移動端瀏覽器,事件執行的順序是touchstart > touchend > click。而click事件有300ms的延遲,當touchstart事件把B元素隱藏之後,隔了300ms,瀏覽器觸發了click事件,但是此時B元素不見了,所以該事件被派發到了A元素身上。如果A元素是一個鏈接,那此時頁面就會意外地跳轉。

什麼時候會觸發點擊穿透

click只是在移動端有300ms的延遲,因此,在移動端開發時,混用click和touch會導致穿透事件。

解決方案

延遲蒙層的消失時間

對於設置蒙層的穿透,可以將這個蒙層消失的時間後移350ms,當然爲了不讓用戶感覺到卡頓,可以先設置這個蒙層的opacity透明度爲0,然後等350ms後,再設置display:none

CSS touch-action

和之前說到的一樣,將touch-action設置爲none,使被覆蓋元素的click事件無法發生。當然我們需要在350ms之後解除這個鎖定,將touch-action恢復爲auto

這種方法的缺點就在於兼容性問題。

使用FastClick

使用fastclick庫,從此所有的點擊事件都使用click,而且不存在300ms延遲。當然也就沒有了點擊穿透問題。

fastclick的用法上面也有談到。

參考鏈接

移動端點擊300ms延遲問題和解決

點擊穿透事件原因及解決辦法

Polyfill

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章