移動瀏覽器原生click事件有300ms的延時,這是瀏覽器爲了區分究竟是雙擊仍是單擊事件。
(實際上有些移動瀏覽器不支持雙擊事件。PC版chrome在手機模式下,當禁止用戶雙擊縮放頁面時(即有viewport meta標籤時,無論user-scalable爲yes或no),雙擊會觸發兩次click事件,但並不會觸發dblclick事件,當容許用戶雙擊縮放頁面時(即沒有viewport meta標籤時),雙擊不會觸發click事件,也不會觸發dblclick事件,而是會縮放頁面;在正常模式下(即PC模式),雙擊會先觸發兩次click事件,而後再觸發一次dblclick事件)
fastclick解決了單擊事件的300ms延遲問題,原理大體以下:
touchstart,touchmove,touchend事件是沒有延遲的,當touchend事件觸發時,若是從touchstart觸發到touchend觸發的過程當中沒有移動且時間間隔沒有超過界限,那麼就執行event.prentDefault()且人爲的在目標元素上派發Click事件(targetElement.dispatchEvent(clickEvent),dispatchEvent派發的事件就跟咱們在瀏覽器中實際操做觸發的事件同樣,可以傳播,即有捕獲階段和冒泡階段)。因爲執行了event.prentDefault(),因此會致使瀏覽器原生的單擊和雙擊事件不會再觸發了。
經過上面的講解,咱們能夠知道,使用fastclick後,是沒法區分單擊和雙擊的,fastclick通通都認爲是單擊事件,因此咱們只能人爲地來模擬單擊事件和雙擊事件(300ms內只有一次點擊爲單擊事件,不然就是雙擊或者多擊事件)。chrome
//給$elem元素自定義click事件
function customClick($elem) {
var lastTouch, //上一次touchstart觸發的時間
touching, //是否正在觸屏
moved, //是否touchmove過
multiClick, //是否單指多擊
multiFinger; //是否多指操做瀏覽器
function onTouchStart(event) {
var t = 300,
time = new Date().getTime();spa
if (event.touches.length !== 1) { //多指操做
multiFinger = true;
} else {
if (lastTouch && time - lastTouch < t) {
//!multiClick && $elem.dblclick(); 雙擊事件
multiClick = true;
} else {
multiClick = false;
moved = false;
multiFinger = false;
setTimeout(function () {
//沒有多指操做過,沒有屢次點擊過,觸屏期間沒有touchmove過,且如今沒有觸屏
!multiFinger && !touching && !multiClick && !moved && $elem.clicked();
}, t);
}
}scala
lastTouch = time;
touching = true;
}事件
function onTouchEnd(event) {
!event.touches.length && (touching = false);
}get
function onTouchMove(event) {
moved = true;
}io
$elem.on('touchstart', onTouchStart).on('touchend', onTouchEnd).on('touchmove', onTouchMove);
}event