最近在復查前輩的代碼時,發現很多需要長按實現某種功能的地方都是用 替代的,原以為長按也是點擊的一種形式,在做過數次測試后,那臉打得 pia、pia、pia,便有了自己封裝一個長按功能的想法。
社會我豬哥,人不狠話也不多。說干就干!
思路分析
移動端的點擊功能(PC端也一樣)js長按按鈕數字增加,分為手指按下()和抬起(),間隔短;而長按功能的“長”字,便可以在“間隔”之上做文章,手指按下和抬起間隔時間達到某個閾值,就稱之為“長按”。
代碼環節
有了上述分析, 竊以為將間隔時間定為 700 毫秒也是可以的。于是乎,就有了如下代碼,僅供參考:
(function(win) {
/**
* 長按功能,長按 700ms 以上即可調用回調方法
*
* @class
*/
class LongPress {
/**
* 構造器
*
* @public
* @param {String} el 需要長按的 DOM 節點名
* @param {function} callback 長按觸發的回調函數
*/
constructor(el, callback) {
this.el = document.querySelector(el);
// 初始化開始時間
this.startTime = 0;
// 初始化結束時間
this.endTime = 0;
this.init(callback);

}
/**
* 初始化
*
* @private
* @param {function} callback 回調函數
*/
init(callback) {
this.touchstart();
this.touchend(callback);
}
/**
* 手指按下時為 startTime 賦值當前時間
*
* @private
*/
touchstart() {
this.el.addEventListener('touchstart', function(event) {
// 清除默認行為
event.preventDefault();
// 記錄手指按下的時間戳
this.startTime = new Date();
});
}

/**
* 手指抬起時為 endTime 賦值當前時間
* 若 endTime 與 startTime 差值大于 700ms, 觸發回調函數
*
* @private
* @param {function} callback 回調函數
*/
touchend(callback) {
this.el.addEventListener('touchend', function(event) {
// 清除默認行為
event.preventDefault();
// 記錄手指抬起的時間戳
this.endTime = new Date();
// 判斷手指按下和抬起的間隔時間是否大于 700 毫秒,大于則表示長按成功
if (this.endTime - this.startTime > 700) {
if (typeof callback === 'function') {
callback();
} else {
console.error('callback is not a function!');
}
}
});
}
}

win.LongPress = LongPress;
})(window);
改進方案
當然,這只是一種形式,它依賴于手指的狀態:只有手指抬起才會觸發回調函數。
那么我們能否再次改進呢?比如,手指不抬起,只要按住時間超過閾值,也能夠觸發回調函數?回答是肯定的,定時器如是說。
我們可以在手指按下時啟動定時器,設置時間間隔,觸發回調函數;手指抬起時,清除定時器。代碼如下:
(function(win) {
/**
* 長按功能,長按 700ms 以上即可調用回調方法
*
* @class
*/
class LongPress {
/**
* 構造器
*
* @public
* @param {String} el 需要長按的 DOM 節點名
* @param {function} callback 長按觸發的回調函數
*/
constructor(el, callback) {
this.el = document.querySelector(el);
this.timer = null;
this.init(callback);
}

/**
* 初始化
*
* @private
* @param {function} callback 回調函數
*/
init(callback) {
this.touchstart(callback);
this.touchend();
}
/**
* 手指按下時開啟定時器,700 毫秒后觸發回調函數
*
* @private
* @param {function} callback 回調函數
*/
touchstart(callback) {
this.el.addEventListener('touchstart', function(event) {
// 清除默認行為
event.preventDefault();
// 開啟定時器
this.timer = setTimeout(() => {
if (typeof callback === 'function') {
callback();

} else {
console.error('callback is not a function!');
}
}, 700);
});
}
/**
* 手指抬起時清除定時器,無論按住時間是否達到 700 毫秒的閾值
*
* @private
*/
touchend() {
this.el.addEventListener('touchend', function(event) {
// 清除默認行為
event.preventDefault();
// 清除定時器
clearTimeout(this.timer);
});
}
}
win.LongPress = LongPress;
})(window);
避坑指南
目前發現有瀏覽器(如微信瀏覽器)在默認行為中添加了長按復制功能,而以上代碼中卻添加了 event.() 清除默認行為,會屏蔽掉瀏覽器自帶的長按功能,所以應視情況而定js長按按鈕數字增加,取消清除默認行為的代碼。