1. 程式人生 > >移動端使用fastclick時,模擬原生瀏覽器對象

移動端使用fastclick時,模擬原生瀏覽器對象

meta 單擊事件 移動 ontouch 通過 out 禁止 multi time

移動瀏覽器原生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內只有一次點擊為單擊事件,否則就是雙擊或者多擊事件)。

//給$elem元素自定義click事件
function customClick($elem) {
var lastTouch, //上一次touchstart觸發的時間
touching, //是否正在觸屏
moved, //是否touchmove過
multiClick, //是否單指多擊
multiFinger; //是否多指操作

function onTouchStart(event) {
var t = 300,
time = new Date().getTime();

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);
}
}

lastTouch = time;
touching = true;
}

function onTouchEnd(event) {
!event.touches.length && (touching = false);
}

function onTouchMove(event) {
moved = true;
}

$elem.on(‘touchstart‘, onTouchStart).on(‘touchend‘, onTouchEnd).on(‘touchmove‘, onTouchMove);
}

移動端使用fastclick時,模擬原生瀏覽器對象