天天看點

移動端300ms延遲和點選穿透一、移動端點選産生300 ms的延遲二、點選穿透參考連結

文章目錄

  • 一、移動端點選産生300 ms的延遲
    • 解決方案
      • 方案一:禁用縮放(HTML文檔頭部設定meta标簽)
      • 方案二:更改預設的視口寬度
      • 方案三:CSS touch-action
      • 方案四:FastClick
      • 方案五:使用touchstart替代click
  • 二、點選穿透
    • 什麼是點選穿透,點選穿透為什麼會發生
    • 什麼時候會觸發點選穿透
    • 解決方案
      • 延遲蒙層的消失時間
      • CSS touch-action
      • 使用FastClick
  • 參考連結

一、移動端點選産生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标簽,那浏覽器就可以認為該網站已經對移動端做過了适配和優化,就無需輕按兩下縮放操作了。

這個方案相比方案一的好處在于,它沒有完全禁用縮放,而隻是禁用了浏覽器預設的輕按兩下縮放行為,但使用者仍然可以通過雙指縮放操作來縮放頁面。

方案三: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