移動端延遲300ms的原因以及解決方案

一、前言

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

二、移動端延遲300ms的原因

為什么要用觸摸事件盖喷?觸摸事件是移動端瀏覽器特有的html5事件爆办。

因為移動端的click有很大延遲(大約300ms),300ms延遲來自判斷雙擊和長按课梳,因為只有默認(rèn)等待時間結(jié)束以確定沒有后續(xù)動作發(fā)生時距辆,才會觸發(fā)click事件。而觸摸事件的延遲則是非常短的暮刃,使用觸摸事件的能夠提高頁面響應(yīng)速度跨算,帶來更好的用戶體驗。

重點:由于移動端會有雙擊縮放的這個操作沾歪,因此瀏覽器在click之后要等待300ms漂彤,****看用戶有沒有下一次點擊,也就是這次操作是不是雙擊灾搏。

三挫望、瀏覽器開發(fā)商的解決方案

1、方案一:禁用縮放

當(dāng)HTML文檔頭部包含如下meta標(biāo)簽時:

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

表明這個頁面是不可縮放的狂窑,那雙擊縮放的功能就沒有意義了媳板,此時瀏覽器可以禁用默認(rèn)的雙擊縮放行為并且去掉300ms的點擊延遲

缺點:就是必須通過完全禁用縮放來達(dá)到去掉點擊延遲的目的泉哈,然而完全禁用縮放并不是我們的初衷蛉幸,我們只是想禁掉默認(rèn)的雙擊縮放行為,這樣就不用等待300ms來判斷當(dāng)前操作是否是雙擊丛晦。但是通常情況下奕纫,我們還是希望頁面能通過雙指縮放來進(jìn)行縮放操作,比如放大一張圖片烫沙,放大一段很小的文字匹层。

2、方案二:更改默認(rèn)的視口窗口

為了讓桌面站點能在移動端瀏覽器正常顯示锌蓄,移動端瀏覽器默認(rèn)的視口寬度升筏!=設(shè)備瀏覽器視窗寬度,而是視口寬度要比設(shè)備寬度大瘸爽,通常是980px您访。

我們可以通過以下標(biāo)簽來設(shè)置視口寬度設(shè)備寬度

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

對移動端坐過適配和優(yōu)化了剪决,這個時候就不需要雙擊縮放了灵汪。如果能夠識別出一個網(wǎng)站是響應(yīng)式的網(wǎng)站檀训,那么移動端瀏覽器就可以自動禁掉默認(rèn)的雙擊縮放行為并且去掉300ms的點擊延遲。如果設(shè)置了上述meta標(biāo)簽识虚,那瀏覽器就可以認(rèn)為該網(wǎng)站已經(jīng)對移動端做過了適配和優(yōu)化肢扯,就無需雙擊縮放操作了妒茬。

這個方案相比方案一的好處在于担锤,它沒有完全禁用縮放,而只是禁用了瀏覽器默認(rèn)的雙擊縮放行為乍钻,但用戶仍然可以通過雙指縮放操作來縮放頁面肛循。

方案三:css 的 touch-action

除了IE之外的大部分瀏覽器都不支持這個新的CSS屬性。touch-action這個CSS屬性银择。這個屬性指定了相應(yīng)元素上能夠觸發(fā)的用戶代理(也就是瀏覽器)的默認(rèn)行為多糠。如果將該屬性值設(shè)置為touch-action: none,那么表示在該元素上的操作不會觸發(fā)用戶代理的任何默認(rèn)行為浩考,就無需進(jìn)行300ms的延遲判斷夹孔。

四、代碼解決方案

1析孽、方案一:指針事件polyfill

除了IE搭伤,其他大部分瀏覽器都還不支持指針事件。有一些JS庫袜瞬,可以讓我們提前使用指針事件怜俐。比如:

(1)谷歌的Polymer

(2)微軟的HandJS

(3)@Rich-HarrisPoints

關(guān)心的不是指針事件,而是與300ms延遲相關(guān)的CSS屬性touch-action邓尤。由于除了IE之外的大部分瀏覽器都不支持這個新的CSS屬性拍鲤,所以這些**指針事件的polyfill必須通過某種方式去模擬支持這個屬性**。一種方案是JS去請求解析所有的樣式表汞扎,另一種方案是將touch-action作為html標(biāo)簽的屬性季稳。

2、方案二:****FastClick

FastClickFT Labs專門為解決移動端瀏覽器 300 毫秒點擊延遲問題所開發(fā)的一個輕量級的庫澈魄。FastClick的實現(xiàn)原理是在檢測到touchend事件的時候景鼠,會通過DOM自定義事件立即出發(fā)模擬一個click事件,并把瀏覽器在300ms之后的click事件阻止掉一忱。

五莲蜘、點擊穿透問題

說完移動端點擊300ms延遲的問題,還不得不提一下移動端點擊穿透的問題帘营。既然click點擊有300ms的延遲票渠,那對于觸摸屏,我們直接監(jiān)聽touchstart事件不就好了嗎芬迄?

使用touchstart去代替click事件有兩個不好的地方问顷。

第一:touchstart是手指觸摸屏幕就觸發(fā),有時候用戶只是想滑動屏幕,卻觸發(fā)了touchstart事件杜窄,這不是我們想要的結(jié)果肠骆;

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

1塞耕、什么是點擊穿透蚀腿?

假如頁面上有兩個元素A和B。B元素在A元素之上扫外。我們在B元素的touchstart事件上注冊了一個回調(diào)函數(shù)莉钙,該回調(diào)函數(shù)的作用是隱藏B元素。我們發(fā)現(xiàn)筛谚,當(dāng)我們點擊B元素磁玉,B元素被隱藏了,隨后驾讲,A元素觸發(fā)了click事件倔约。

這是因為在移動端瀏覽器爽醋,事件執(zhí)行的順序是touchstart > touchend > click。而click事件有300ms的延遲,當(dāng)touchstart事件把B元素隱藏之后樱哼,隔了300ms凌简,瀏覽器觸發(fā)了click事件依沮,但是此時B元素不見了盗舰,所以該事件被派發(fā)到了A元素身上。如果A元素是一個鏈接扎谎,那此時頁面就會意外地跳轉(zhuǎn)碳想。

2、點擊穿透現(xiàn)象3種情況

(1)點擊穿透問題:點擊蒙層(mask)上的關(guān)閉按鈕毁靶,蒙層消失后發(fā)現(xiàn)觸發(fā)了按鈕下面元素的click事件胧奔。

(2)跨頁面點擊穿透問題:如果按鈕下面恰好是一個有href屬性的a標(biāo)簽,那么頁面就會發(fā)生跳轉(zhuǎn)因為 a標(biāo)簽跳轉(zhuǎn)默認(rèn)是click事件觸發(fā) 预吆,所以原理和上面的完全相同

(3)點擊穿透問題:這次沒有mask了龙填,直接點擊頁內(nèi)按鈕跳轉(zhuǎn)至新頁,然后發(fā)現(xiàn)新頁面中對應(yīng)位置元素的click事件被觸發(fā)了拐叉。

3岩遗、解決方案

2種思路:

(1)不要混用touch和click。既然touch之后300ms會觸發(fā)click凤瘦,只用touch或者只用click就自然不會存在問題了宿礁。

(2)用掉(或者說是消費掉)touch之后的click。依舊用tap蔬芥,只是在可能發(fā)生點擊穿透的情形做額外的處理梆靖,拿個東西來擋住控汉、或者tap后延遲350毫秒再隱藏mask、pointer-events返吻、在下面元素的事件處理器里做檢測(配合全局flag)

詳細(xì)方案:

(1)只用touch

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

把頁面內(nèi)所有click全部換成touch事件 touchstart 测僵、’touchend’街佑、’tap’, 需要特別注意 a標(biāo)簽恨课,a標(biāo)簽的href也是click舆乔,需要去掉換成js控制的跳轉(zhuǎn)岳服,或者直接改成span + tap控制跳轉(zhuǎn)剂公。

(2)只用click

下下策 ,因為會帶來300ms延遲吊宋,頁面內(nèi)任何一個自定義交互都將增加300毫秒延遲纲辽,想想都慢。不用touch就不會存在touch之后300ms觸發(fā)click的問題璃搜。

(3)拿個東西擋住

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

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

改動最小这吻,缺點是隱藏mask變慢了吊档,350ms還是能感覺到慢的。

(5)pointer-events

比較麻煩且有缺陷唾糯, 不建議使用怠硼。mask隱藏后,給按鈕下面元素添上 pointer-events: none; 樣式移怯,讓click穿過去香璃,350ms后去掉這個樣式,恢復(fù)響應(yīng)舟误。缺陷是mask消失后的的350ms內(nèi)葡秒,用戶可以看到按鈕下面的元素點著沒反應(yīng),如果用戶手速很快的話一定會發(fā)現(xiàn)嵌溢。

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

比較麻煩眯牧, 不建議使用。全局flag記錄按鈕點擊的位置(坐標(biāo)點)赖草,在下面元素的事件處理器里判斷event的坐標(biāo)點学少,如果相同則是那個可惡的click,拒絕響應(yīng)疚顷。

(7)fastclick

好用的解決方案旱易,不介意多加載幾KB的話禁偎, 不建議使用 ,因為有人遇到了bug阀坏,更多信息請查看: Fastclick 導(dǎo)致click事件觸發(fā)兩次的問題如暖。

首先引入fastclick庫,再把頁面內(nèi)所有touch事件都換成click忌堂,其實稍微有點麻煩盒至,建議引入這幾KB就為了解決點透問題不值得,不如用第一種方法呢士修。

六枷遂、瀏覽器事件觸發(fā)的順序

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

Touch 事件中,常用的為 touchstart, touchmove, touchend 三種棋嘲。除此之外還有touchcancel酒唉。 注意,原生事件中并沒有tap事件沸移。

事件描述如下:

事件 描述 觸發(fā)時機(jī)
touchstart 開始觸摸 手指接觸屏幕時立即觸發(fā)
touchmove 移動或拖拽 取決于系統(tǒng)和瀏覽器
touchend 觸摸結(jié)束 手指離開屏幕時立即出發(fā)

而Touch事件的觸發(fā)一般通過手指痪伦,還會存在多點觸控,拖拽方向等情況雹锣。列出幾個重要參數(shù)如下:

參數(shù) 含義
touches 屏幕中每根手指信息列表
targetTouches 和touches類似网沾,把同一節(jié)點的手指信息過濾掉
changedTouches 響應(yīng)當(dāng)前事件的每根手指的信息列表

代碼獲取如下:

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

手指觸發(fā)觸摸事件的過程如下:

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

由此,我們可以在 ontouchstart 事件上記錄開始觸摸開始蕊爵,ontouchend 記錄觸摸結(jié)束信息辉哥。 通過上述這些參數(shù),很容易的去計算幽冥點擊的時間攒射,以及點擊穿透的相關(guān)信息醋旦,包括響應(yīng)的坐標(biāo)情況

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末匆篓,一起剝皮案震驚了整個濱河市浑度,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌鸦概,老刑警劉巖箩张,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異窗市,居然都是意外死亡先慷,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進(jìn)店門咨察,熙熙樓的掌柜王于貴愁眉苦臉地迎上來论熙,“玉大人,你說我怎么就攤上這事摄狱∨Ч睿” “怎么了无午?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長祝谚。 經(jīng)常有香客問我宪迟,道長,這世上最難降的妖魔是什么交惯? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任次泽,我火速辦了婚禮,結(jié)果婚禮上席爽,老公的妹妹穿的比我還像新娘意荤。我一直安慰自己,他們只是感情好只锻,可當(dāng)我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布玖像。 她就那樣靜靜地躺著,像睡著了一般炬藤。 火紅的嫁衣襯著肌膚如雪御铃。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天沈矿,我揣著相機(jī)與錄音,去河邊找鬼咬腋。 笑死羹膳,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的根竿。 我是一名探鬼主播陵像,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼寇壳!你這毒婦竟也來了醒颖?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤壳炎,失蹤者是張志新(化名)和其女友劉穎泞歉,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體匿辩,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡腰耙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了铲球。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片挺庞。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖稼病,靈堂內(nèi)的尸體忽然破棺而出选侨,到底是詐尸還是另有隱情掖鱼,我是刑警寧澤,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布援制,位于F島的核電站锨用,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏隘谣。R本人自食惡果不足惜增拥,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望寻歧。 院中可真熱鬧掌栅,春花似錦、人聲如沸码泛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽噪珊。三九已至晌缘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間痢站,已是汗流浹背磷箕。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留阵难,地道東北人岳枷。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像呜叫,于是被迫代替她去往敵國和親空繁。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,629評論 2 354

推薦閱讀更多精彩內(nèi)容