設計方案--移動端延遲300ms的緣由以及解決方案

1、前言javascript

移動端瀏覽器提供一個特殊的功能:雙擊(double tap)縮放。css

 

2、移動端延遲300ms的緣由html

爲何要用觸摸事件?觸摸事件是移動端瀏覽器特有的html5事件。html5

由於移動端的click有很大延遲(大約300ms),300ms延遲來自判斷雙擊和長按,由於只有默認等待時間結束以肯定沒有後續動做發生時,纔會觸發click事件。而觸摸事件的延遲則是很是短的,使用觸摸事件的可以提升頁面響應速度,帶來更好的用戶體驗。java

重點:因爲移動端會有雙擊縮放的這個操做,所以瀏覽器在click以後要等待300ms,看用戶有沒有下一次點擊,也就是此次操做是否是雙擊。git

 

3、瀏覽器開發商的解決方案github

一、方案一:禁用縮放瀏覽器

當HTML文檔頭部包含以下meta標籤時:函數

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

代表這個頁面是不可縮放的,那雙擊縮放的功能就沒有意義了,此時瀏覽器能夠禁用默認的雙擊縮放行爲而且去掉300ms的點擊延遲學習

缺點:就是必須經過徹底禁用縮放來達到去掉點擊延遲的目的,然而徹底禁用縮放並非咱們的初衷,咱們只是想禁掉默認的雙擊縮放行爲,這樣就不用等待300ms來判斷當前操做是不是雙擊。可是一般狀況下,咱們仍是但願頁面能經過雙指縮放來進行縮放操做,好比放大一張圖片,放大一段很小的文字。

 

二、方案二:更改默認的視口窗口

爲了讓桌面站點能在移動端瀏覽器正常顯示,移動端瀏覽器默認的視口寬度!=設備瀏覽器視窗寬度,而是視口寬度要比設備寬度大,一般是980px。

咱們能夠經過如下標籤來設置視口寬度設備寬度

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

對移動端坐過適配和優化了,這個時候就不須要雙擊縮放了。若是可以識別出一個網站是響應式的網站,那麼移動端瀏覽器就能夠自動禁掉默認的雙擊縮放行爲而且去掉300ms的點擊延遲。若是設置了上述meta標籤,那瀏覽器就能夠認爲該網站已經對移動端作過了適配和優化,就無需雙擊縮放操做了。

這個方案相比方案一的好處在於,它沒有徹底禁用縮放,而只是禁用了瀏覽器默認的雙擊縮放行爲,但用戶仍然能夠經過雙指縮放操做來縮放頁面

 

方案三:css 的 touch-action

除了IE以外的大部分瀏覽器都不支持這個新的CSS屬性。touch-action這個CSS屬性。這個屬性指定了相應元素上可以觸發的用戶代理(也就是瀏覽器)的默認行爲。若是將該屬性值設置爲touch-action: none,那麼表示在該元素上的操做不會觸發用戶代理的任何默認行爲,就無需進行300ms的延遲判斷

 

4、代碼解決方案

一、方案一:指針事件polyfill

除了IE,其餘大部分瀏覽器都還不支持指針事件。有一些JS庫,可讓咱們提早使用指針事件。好比:

(1)谷歌的Polymer

(2)微軟的HandJS

(3)@Rich-Harris 的 Points

關心的不是指針事件,而是與300ms延遲相關的CSS屬性touch-action。因爲除了IE以外的大部分瀏覽器都不支持這個新的CSS屬性,因此這些指針事件的polyfill必須經過某種方式去模擬支持這個屬性。一種方案是JS去請求解析全部的樣式表,另外一種方案是將touch-action做爲html標籤的屬性。

 

二、方案二:FastClick

FastClickFT Labs專門爲解決移動端瀏覽器 300 毫秒點擊延遲問題所開發的一個輕量級的庫。FastClick的實現原理是在檢測到touchend事件的時候,會經過DOM自定義事件當即出發模擬一個click事件,並把瀏覽器在300ms以後的click事件阻止掉。

 

5、點擊穿透問題

說完移動端點擊300ms延遲的問題,還不得不提一下移動端點擊穿透的問題。既然click點擊有300ms的延遲,那對於觸摸屏,咱們直接監聽touchstart事件不就行了嗎?

使用touchstart去代替click事件有兩個很差的地方。

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

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

一、什麼是點擊穿透?

假如頁面上有兩個元素A和B。B元素在A元素之上。咱們在B元素的touchstart事件上註冊了一個回調函數,該回調函數的做用是隱藏B元素。咱們發現,當咱們點擊B元素,B元素被隱藏了,隨後,A元素觸發了click事件。

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

 

二、點擊穿透現象3種狀況

(1)點擊穿透問題:點擊蒙層(mask)上的關閉按鈕,蒙層消失後發現觸發了按鈕下面元素的click事件。

(2)跨頁面點擊穿透問題:若是按鈕下面剛好是一個有href屬性的a標籤,那麼頁面就會發生跳轉由於 a標籤跳轉默認是click事件觸發 ,因此原理和上面的徹底相同

(3)點擊穿透問題:此次沒有mask了,直接點擊頁內按鈕跳轉至新頁,而後發現新頁面中對應位置元素的click事件被觸發了。

 

三、解決方案

2種思路:

(1)不要混用touch和click。既然touch以後300ms會觸發click,只用touch或者只用click就天然不會存在問題了。

(2)用掉(或者說是消費掉)touch以後的click。依舊用tap,只是在可能發生點擊穿透的情形作額外的處理,拿個東西來擋住、或者tap後延遲350毫秒再隱藏mask、pointer-events、在下面元素的事件處理器裏作檢測(配合全局flag)

詳細方案:

(1)只用touch

最簡單的解決方案,完美解決點擊穿透問題。

把頁面內全部click所有換成touch事件 touchstart 、’touchend’、’tap’, 須要特別注意 a標籤,a標籤的href也是click,須要去掉換成js控制的跳轉,或者直接改爲span + tap控制跳轉。

(2)只用click

下下策 ,由於會帶來300ms延遲,頁面內任何一個自定義交互都將增長300毫秒延遲,想一想都慢。不用touch就不會存在touch以後300ms觸發click的問題。

(3)拿個東西擋住

比較笨的方法, 千萬不要用。更多信息請查看 【移動端兼容問題研究】javascript事件機制詳解(涉及移動兼容)

(4)tap後延遲350ms再隱藏mask

改動最小,缺點是隱藏mask變慢了,350ms仍是能感受到慢的。

(5)pointer-events

比較麻煩且有缺陷, 不建議使用。mask隱藏後,給按鈕下面元素添上 pointer-events: none; 樣式,讓click穿過去,350ms後去掉這個樣式,恢復響應。缺陷是mask消失後的的350ms內,用戶能夠看到按鈕下面的元素點着沒反應,若是用戶手速很快的話必定會發現。

(6)在下面元素的事件處理器裏作檢測(配合全局flag)

比較麻煩, 不建議使用。全局flag記錄按鈕點擊的位置(座標點),在下面元素的事件處理器裏判斷event的座標點,若是相同則是那個可惡的click,拒絕響應。

(7)fastclick

好用的解決方案,不介意多加載幾KB的話, 不建議使用 ,由於有人遇到了bug,更多信息請查看: Fastclick 致使click事件觸發兩次的問題

 

首先引入fastclick庫,再把頁面內全部touch事件都換成click,其實稍微有點麻煩,建議引入這幾KB就爲了解決點透問題不值得,不如用第一種方法呢。

 

6、瀏覽器事件觸發的順序

touchstart --> mouseover(有的瀏覽器沒有實現) --> mousemove(一次) -->mousedown --> mouseup --> click -->touchend

Touch 事件中,經常使用的爲 touchstart, touchmove, touchend 三種。除此以外還有touchcancel。 注意,原生事件中並無tap事件。

事件描述以下:

事件 描述 觸發時機
touchstart 開始觸摸 手指接觸屏幕時當即觸發
touchmove 移動或拖拽 取決於系統和瀏覽器
touchend 觸摸結束 手指離開屏幕時當即出發

而Touch事件的觸發通常經過手指,還會存在多點觸控,拖拽方向等狀況。列出幾個重要參數以下:

參數 含義
touches 屏幕中每根手指信息列表
targetTouches 和touches相似,把同一節點的手指信息過濾掉
changedTouches 響應當前事件的每根手指的信息列表

代碼獲取以下:

elemenrRef.addEventListener('touchstart', function(e) { console.log(e.touches, e.targetTouches, e.changedTouches);} );

 

手指觸發觸摸事件的過程以下:

touchstart --> mouseover(有的瀏覽器沒有實現) --> mousemove(一次) -->mousedown --> mouseup --> click -->touchend

由此,咱們能夠在 ontouchstart 事件上記錄開始觸摸開始,ontouchend 記錄觸摸結束信息。 經過上述這些參數,很容易的去計算幽冥點擊的時間,以及點擊穿透的相關信息,包括響應的座標狀況

 

【注:我是saucxs,也叫songEagle,鬆寶寫代碼,文章首發於sau交流學習社區 https://www.mwcxs.top),關注咱們天天閱讀更多精彩內容】

原文出處:https://www.cnblogs.com/chengxs/p/11064469.html

相關文章
相關標籤/搜索