300ms問題的由來
瀏覽器會等待300ms以確定用戶是想單擊還是雙擊。
最初是ios safari 為了解決手機端瀏覽pc網頁時無法確定用戶是單擊還是雙擊縮放而設定了300ms等待這樣一個約定,后來其他手機瀏覽器都復制了這個約定。但隨著移動端web發展,對使用體驗要求也越來越高,300ms的卡頓越來越難以接受。
目前的解決方案
歸結起來是兩個辦法:
一、禁用雙擊縮放(meta 標簽、touch-action都屬于這類)
二、監聽事件,不等300ms就觸發,再移除300ms后的click事件(使用第三方庫例如fastclick)
1.meta標簽禁止縮放
<meta name="viewport" content="user-scalable=no">
<meta name="viewport" content="initial-scale=1,maximum-scale=1">
2.瀏覽器會在視口寬度設置為設備寬度
<meta name="viewport" content="width=device-width">
時停用雙擊縮放行為,chrome 32開始支持,其他廠商也開始支持.
3.指針事件
touch-action屬性規定了觸摸輸入能否觸發UA的默認行為。
- auto:允許瀏覽器處理各類手勢
- none:禁止瀏覽器處理各類手勢
- manipulation: 允許平移,雙指縮放,禁止雙擊縮放
支持情況:
4.fastclick 見下文
React-fastclick
give up, 存在點透問題
fastclick
FastClick is a simple, easy-to-use library for eliminating the 300ms delay between a physical tap and the firing of a click event on mobile browsers. The aim is to make your application feel less laggy and more responsive while avoiding any interference with your current logic.
原理:
移動端點擊事件發生時,會觸發touchStart => touchMove => touchEnd => click ,fastclick是在監聽到touchEnd事件時,觸發click事件,關鍵代碼:
FastClick.prototype.onTouchEnd = function(event) {
...
this.sendClick(targetElement, event);
event.preventDefault();
...
};
FastClick.prototype.sendClick = function(targetElement, event) {
var clickEvent, touch;
...
// Synthesise a click event, with an extra attribute so it can be tracked
clickEvent = document.createEvent('MouseEvents');
clickEvent.initMouseEvent(this.determineEventType(targetElement), true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);
clickEvent.forwardedTouchEvent = true;
targetElement.dispatchEvent(clickEvent);
};
引入:
import fastclick from 'fastclick';
fastclick.attach(document.body);
缺點:
文件大小:26k => 10k左右
Reference
1.http://www.lxweimin.com/p/459102cd0ee9
2.https://developer.mozilla.org/en-US/docs/Web/CSS/touch-action