一、移動端click點擊事件300ms延遲介紹
在正常情況下,如果不進行特殊處理,移動端在觸發(fā)點擊事件時,會有300ms的延遲。換句話說,當我們在點擊移動端頁面后不會立即做出反應(yīng),而是會等待300ms才會觸發(fā)click事件。在移動web興起初期,用戶對300ms的延遲沒有太大的感覺,但隨著用戶對交互體驗的要求的提高,如今,移動端的300ms延遲嚴重影響了用戶體驗。
300ms延遲由來
07年,蘋果公司發(fā)布首款I(lǐng)phone前夕,遇到一個問題:當時的網(wǎng)站都是為大屏設(shè)計,手機屏幕太小無法正常瀏覽,于是蘋果工程師做了一些約定解決此類問題。
這些約定當中,最為有名的是雙擊縮放(double tap to zoom),這是產(chǎn)生300ms延遲的根源。
用手指在屏幕上快速點擊兩次,iOS 自帶的 Safari 瀏覽器會將網(wǎng)頁縮放至原始比例。如果用戶在 iOS Safari
里邊點擊了一個鏈接。由于用戶可以進行雙擊縮放或者雙擊滾動的操作,當用戶一次點擊屏幕之后,瀏覽器并不能立刻判斷用戶是確實要打開這個鏈接,還是想要進行雙擊操作。因此,iOS
Safari 就等待 300 毫秒,以判斷用戶是否再次點擊了屏幕。 鑒于iPhone的成功,其他移動瀏覽器都復(fù)制了 iPhone
Safari 瀏覽器的多數(shù)約定,包括雙擊縮放,幾乎現(xiàn)在所有的移動端瀏覽器都有這個功能。 由此產(chǎn)生了300ms延遲問題。
解決方案
方案一 禁用縮放
在html文檔頭部的meta標簽中加入如下語句:
<!-- 1.禁用縮放 user-scalable=no -->
<meta name="viewport" content="width=device-width, initial-scale=1.0,user-scalable=no">
user-scalable=no表明這個頁面不可縮放,也就是瀏覽器禁用的雙擊縮放事件并且同時會去掉300ms點擊延遲。
但這個方案也有缺點,就是完全禁用了雙擊縮放,當我們需要放大文字或者圖片時無法滿足我們的需求。
方案二 封裝一個處理函數(shù)
//封裝tap解決click 300ms 延時
function tap (obj,callback) {
var isMove = false;//記錄手指是否移動
var startTime = 0;//記錄手指觸摸的時間
obj.addEventListerner('touchstart',function(e){
startTime = Date.now();//記錄觸摸時間
})
obj.addEventListerner('touchmove',function(e){
isMove = true;//查看手指是否滑動
})
obj.addEventListerner('touchend',function(e){
if(!isMove && (Date.now()-statrTime) < 150){
callback && callback();
}
isMove = false;//取反 重置
startTime = 0;
})
};
tap(div,function(){ //執(zhí)行代碼 });
這個代碼可以監(jiān)測元素點擊發(fā)生時的狀態(tài),從而避免300ms的延遲。
但這個方法有一個弊端,一次只能給一個元素去解決問題。
方案三 fastclick插件解決問題
安裝fastclick可以使用npm,Component和Bower。另外也提供了Ruby版的gem fastclick-rails以及.NET提供了NuGet package。最直接的可以在頁面引入fastclick js文件。如:
fastclick插件下載地址
插件下載后,在頁面中直接引入fastclick.js
import FastClick from 'fastclick';
// hack 在ios 11.3移動端頁面 input輸入框第一次觸摸可以彈起鍵盤,后續(xù)再觸摸需要很難彈起鍵盤,或者需要在輸入框停一會才能彈起鍵盤。
FastClick.prototype.focus = (targetElement) => {
targetElement.focus();
};
if ('addEventListener' in document) {
document.addEventListener('DOMContentLoaded', () => {
FastClick.attach(document.body);
}, false);
}