1.前言
在word中,當我們需要刪除一大段文本的時候,我們按一下鍵盤上的退格鍵,就會刪除一個字,當我們長按住退格鍵時,就會連續不停的刪除,這就是鍵盤按鍵的長按功能。那么我們也想在網頁中讓一個按鈕也具有“長按”和“單擊”不同的功能,該怎樣實現呢?下面我們采用vue自定義指令的方式,來實現一個長按指令。
2.原理
長按,即用戶按下按鈕並持續按住幾秒鍾,即觸發長按功能。那么,要實現這樣的功能關鍵點在於我們需要知道的是用戶什么時候按下按鈕和什么時候松開按鈕。幸運的是:瀏覽器在當用戶點擊鼠標時提供給了我們兩個事件: mousedown 和 mouseup。當用戶按下鼠標時會觸發 mousedown 事件,用戶松開鼠標時會觸發 mouseup 事件。有了這兩個事件,我們只需這樣做:
1.當mousedown 事件觸發時,啟動一個計時器,開始計時。
2.設定一個時間閾值,比如2秒。在時間閾值內如果 mouseup 事件被觸發了,即認為這是一次普通的單擊,不執行長按功能函數並清除定時器。反之,超出時間閾值后 mouseup 事件才被觸發,即認為用戶在長按按鈕,此時執行長按功能函數。
3.實現
3.1 計時器變量
首先,我們定義一個變量timer,用於存儲定時器,並設置初始值未null。
let timer = null
3.2 啟動函數
該函數是當瀏覽器監聽到mousedown事件觸發后執行的回調函數,該函數主要作用是創建並啟動定時器,並且在設定的時間閾值內如果mouseup還未觸發,則執行長按功能函數。函數代碼如下:
var start = function (e) { // 如果是點擊事件,不啟動計時器,直接返回 if (e.type === 'click'){ return } if (timer == null){ // 創建定時器 ( 2s之后執行長按功能函數 ) timer = setTimeout(function () { //執行長按功能函數 longFunc() },2000) } }
3.3 取消函數
該函數是當瀏覽器監聽到mouseup事件觸發后執行的回調函數,該函數主要作用是清除定時器。函數代碼如下:
var cancel = function () { if (timer !== null){ clearTimeout(timer) timer = null } }
3.4 設置事件監聽器
設置事件監聽器,用於監聽mousedown、mouseup和click事件,分別執行不同的回調函數。
// 添加事件監聽器 el.addEventListener("mousedown", start); // 長按事件取消,取消計時器 el.addEventListener("click", cancel); el.addEventListener("mouseout", cancel);
4. 定義vue指令
有了上面的工作后,我們就可以定義vue指令了:
Vue.directive('longpress', function (el, binding){ var timer = null; var start = function (e) { // 如果是點擊事件,不啟動計時器,直接返回 if (e.type === 'click'){ return } if (timer == null){ // 創建定時器 ( 2s之后執行長按功能函數 ) timer = setTimeout(function () { //執行長按功能函數 binding.value() },2000) } } var cancel = function () { if (timer !== null){ clearTimeout(timer) timer = null } } // 添加事件監聽器 el.addEventListener("mousedown", start); // 取消計時器 el.addEventListener("click", cancel); el.addEventListener("mouseout", cancel); })
代碼中el表示指令綁定的元素,binding表示傳遞給指令的值,詳細請參考官方文檔自定義指令。
5. 使用指令
到這里,我們就可以在模板中愉快的使用指令啦。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> {{value}} <button @click="incrementPlusOne" v-longpress="incrementPlusTen">該按鈕具有長按功能哦!!!</button> </div> <script src="vue.js"></script> <script type="text/javascript"> Vue.directive('longpress', function (el, binding){ var timer = null; var start = function (e) { // 如果是點擊事件,不啟動計時器,直接返回 if (e.type === 'click'){ return } if (timer == null){ // 創建定時器 ( 2s之后執行長按功能函數 ) timer = setTimeout(function () { //執行長按功能函數 binding.value() },2000) } } var cancel = function () { if (timer !== null){ clearTimeout(timer) timer = null } } // 添加事件監聽器 el.addEventListener("mousedown", start); // 取消計時器 el.addEventListener("click", cancel); el.addEventListener("mouseout", cancel); }) new Vue({ el:"#app", data(){ return{ value:10 } }, methods: { // 增加1 incrementPlusOne() { this.value++ }, // 增加10 incrementPlusTen() { this.value += 10 } } }) </script> </body> </html>
6.適配移動端
其實,按鈕長按功能在移動觸屏終端遠比PC端實用的多,要想讓這個指令也適配移動觸屏端,我們只需在監聽一下移動端特有的觸摸事件 touchstart、touchend 和 touchcancel 事件即可。
// 添加事件監聽器 el.addEventListener("mousedown", start); el.addEventListener("touchstart", start); // 取消計時器 el.addEventListener("click", cancel); el.addEventListener("mouseout", cancel); el.addEventListener("touchend", cancel); el.addEventListener("touchcancel", cancel);
(完)