移動(dòng)端300ms延遲原因
2007 年初踏志。蘋(píng)果公司在發(fā)布首款 iPhone 前夕,遇到一個(gè)問(wèn)題:當(dāng)時(shí)的網(wǎng)站都是為大屏幕設(shè)備所設(shè)計(jì)的胀瞪。于是蘋(píng)果的工程師們做了一些約定针余,應(yīng)對(duì) iPhone 這種小屏幕瀏覽桌面端站點(diǎn)的問(wèn)題饲鄙。
雙擊縮放(double tap to zoom),這也是會(huì)有上述 300 毫秒延遲的主要原因圆雁。雙擊縮放忍级,即用手指在屏幕上快速點(diǎn)擊兩次,iOS 自帶的 Safari 瀏覽器會(huì)將網(wǎng)頁(yè)縮放至原始比例伪朽。
假定這么一個(gè)場(chǎng)景轴咱。用戶(hù)在 iOS Safari 里邊點(diǎn)擊了一個(gè)鏈接。由于用戶(hù)可以進(jìn)行雙擊縮放或者單擊跳轉(zhuǎn)的操作烈涮,當(dāng)用戶(hù)一次點(diǎn)擊屏幕之后朴肺,瀏覽器并不能立刻判斷用戶(hù)是確實(shí)要打開(kāi)這個(gè)鏈接,還是想要進(jìn)行雙擊操作坚洽。因此戈稿,iOS Safari 就等待 300 毫秒,以判斷用戶(hù)是否再次點(diǎn)擊了屏幕讶舰。 鑒于iPhone的成功鞍盗,其他移動(dòng)瀏覽器都復(fù)制了 iPhone Safari 瀏覽器的多數(shù)約定,包括雙擊縮放跳昼,幾乎現(xiàn)在所有的移動(dòng)端瀏覽器都有這個(gè)功能橡疼。
解決方案
1.faskclick https://github.com/ftlabs/fastc
- 原理: 在檢測(cè)到touchend事件的時(shí)候,會(huì)通過(guò)DOM自定義事件立即出發(fā)模擬一個(gè)click事件庐舟,并把瀏覽器在300ms之后真正的click事件阻止掉
- 缺點(diǎn): 腳本相對(duì)較大, 不建議使用
2.禁用瀏覽器縮放
<meta name="viewport" content="user-scalable=no">
<meta name="viewport" content="initial-scale=1, maximum-scale=1">
表明這個(gè)頁(yè)面是不可縮放的欣除,那雙擊縮放的功能就沒(méi)有意義了,此時(shí)瀏覽器可以禁用默認(rèn)的雙擊縮放行為并且去掉300ms的點(diǎn)擊延遲挪略。 這個(gè)方案有一個(gè)缺點(diǎn)历帚,就是必須通過(guò)完全禁用縮放來(lái)達(dá)到去掉點(diǎn)擊延遲的目的,然而完全禁用縮放并不是我們的初衷杠娱,我們只是想禁掉默認(rèn)的雙擊縮放行為挽牢,這樣就不用等待300ms來(lái)判斷當(dāng)前操作是否是雙擊。但是通常情況下摊求,我們還是希望頁(yè)面能通過(guò)雙指縮放來(lái)進(jìn)行縮放操作禽拔,比如放大一張圖片,放大一段很小的文字室叉。
3.更改默認(rèn)的視口寬度
<meta name="viewport" content="width=device-width">
一開(kāi)始睹栖,因?yàn)殡p擊縮放主要是用來(lái)改善桌面站點(diǎn)在移動(dòng)端瀏覽體驗(yàn)的。 隨著發(fā)展現(xiàn)在都是專(zhuān)門(mén)為移動(dòng)開(kāi)發(fā)專(zhuān)門(mén)的站點(diǎn)茧痕,這個(gè)時(shí)候就不需要雙擊縮放了野来,所以移動(dòng)端瀏覽器就可以自動(dòng)禁掉默認(rèn)的雙擊縮放行為并且去掉300ms的點(diǎn)擊延遲。如果設(shè)置了上述meta標(biāo)簽踪旷,那瀏覽器就可以認(rèn)為該網(wǎng)站已經(jīng)對(duì)移動(dòng)端做過(guò)了適配和優(yōu)化曼氛,就無(wú)需雙擊縮放操作了豁辉。 這個(gè)方案相比方案一的好處在于,它沒(méi)有完全禁用縮放舀患,而只是禁用了瀏覽器默認(rèn)的雙擊縮放行為徽级,但用戶(hù)仍然可以通過(guò)雙指縮放操作來(lái)縮放頁(yè)面。
4.通過(guò) touchstart 和 touchend模擬實(shí)現(xiàn)
能不能直接touchstart代替click呢聊浅,
答案是不能餐抢,使用touchstart去代替click事件有兩個(gè)不好的地方。
第一:touchstart是手指觸摸屏幕就觸發(fā)狗超,有時(shí)候用戶(hù)只是想滑動(dòng)屏幕,卻觸發(fā)了touchstart事件朴下,這不是我們想要的結(jié)果努咐;
第二:使用touchstart事件在某些場(chǎng)景下可能會(huì)出現(xiàn)點(diǎn)擊穿透的現(xiàn)象。
什么是點(diǎn)擊穿透殴胧?
假如頁(yè)面上有兩個(gè)元素A和B渗稍。B元素在A元素之上。我們?cè)贐元素的touchstart事件上注冊(cè)了一個(gè)回調(diào)函數(shù)团滥,該回調(diào)函數(shù)的作用是隱藏B元素竿屹。我們發(fā)現(xiàn),當(dāng)我們點(diǎn)擊B元素灸姊,B元素被隱藏了拱燃,隨后,A元素觸發(fā)了click事件力惯。
這是因?yàn)樵谝苿?dòng)端瀏覽器碗誉,事件執(zhí)行的順序是touchstart > touchend > click。而click事件有300ms的延遲父晶,當(dāng)touchstart事件把B元素隱藏之后哮缺,隔了300ms,瀏覽器觸發(fā)了click事件甲喝,但是此時(shí)B元素不見(jiàn)了磷醋,所以該事件被派發(fā)到了A元素身上狰闪。如果A元素是一個(gè)鏈接,那此時(shí)頁(yè)面就會(huì)意外地跳轉(zhuǎn)。 任何形式的轉(zhuǎn)載都請(qǐng)聯(lián)系作者獲得授權(quán)并注明出處器联。