詳解如何在Vue里建立長(zhǎng)按指令
您是否曾想過(guò)按住按鈕幾秒鐘才能在Vue應(yīng)用程序中執(zhí)行某個(gè)功能?
您是否曾想在應(yīng)用程序上創(chuàng)建一個(gè)按鈕,通過(guò)按一次(或按住按鈕的整個(gè)輸入)來(lái)清除單個(gè)輸入?
如果你曾有過(guò)這些想法,很好,我也是。那么恭喜你看到了這篇文章。
本文將解釋如何通過(guò)按下(或按?。┌粹o來(lái)執(zhí)行功能和刪除輸入。
首先,我將解釋如何在VanillaJS中實(shí)現(xiàn)這一目標(biāo)。然后,為它創(chuàng)建一個(gè)Vue指令。
那么,讓我們開始吧。
原理
為了實(shí)現(xiàn)長(zhǎng)按,用戶需要按住按鈕幾秒鐘。
要在代碼中復(fù)制它,我們需要在按下鼠標(biāo)“單擊”按鈕時(shí)監(jiān)聽,啟動(dòng)計(jì)時(shí)器,不管我們希望用戶在執(zhí)行函數(shù)之前按住按鈕,并在時(shí)間設(shè)置之后執(zhí)行該功能。
非常簡(jiǎn)單!但是,我們需要知道用戶何時(shí)按住該按鈕。
怎么做
當(dāng)用戶單擊按鈕時(shí),在單擊事件之前會(huì)觸發(fā)另外兩個(gè)事件: mousedown 和 mouseup 。
當(dāng)用戶按下鼠標(biāo)按鈕時(shí)會(huì)調(diào)用 mousedown 事件,而當(dāng)用戶釋放該按鈕時(shí)會(huì)調(diào)用mouseup事件。
我們需要做的就是:
發(fā)生mousedown事件后啟動(dòng)計(jì)時(shí)器。
清除該計(jì)時(shí)器,并且在2secs標(biāo)記之前觸發(fā)mouseup事件后不執(zhí)行該函數(shù)。即完整點(diǎn)擊事件。
只要計(jì)時(shí)器在到達(dá)那個(gè)時(shí)間之前沒有被清除,我們就會(huì)發(fā)現(xiàn)mouseup事件沒有被觸發(fā) - 我們可以說(shuō)用戶沒有釋放按鈕。因此,它被認(rèn)為是長(zhǎng)按,然后我們可以繼續(xù)執(zhí)行所述功能。
實(shí)際操作
讓我們深入研究代碼并完成這項(xiàng)工作。
首先,我們必須定義3件事,即:
variable 用于存儲(chǔ)計(jì)時(shí)器。
start 函數(shù)啟動(dòng)計(jì)時(shí)器。
cancel 函數(shù)取消定時(shí)器
變量
這個(gè)變量基本上保存了setTimeout的值,所以我們可以在發(fā)生mouseup事件時(shí)取消它。
let pressTimer = null;
我們將變量設(shè)置為null,這樣我們就可以檢查變量,以便知道當(dāng)前是否有一個(gè)活動(dòng)定時(shí)器,然后才能取消它。
啟動(dòng)功能
該函數(shù)由setTimeout組成,它基本上是Javascript中的一種方法,它允許我們?cè)诤瘮?shù)中聲明的特定持續(xù)時(shí)間之后執(zhí)行函數(shù)。
請(qǐng)記住,在創(chuàng)建click事件的過(guò)程中,會(huì)觸發(fā)兩個(gè)事件。但我們需要啟動(dòng)計(jì)時(shí)器的是mousedown事件。因此,如果是單擊事件,我們不需要啟動(dòng)計(jì)時(shí)器。
// Create timeout ( run function after 1s ) let start = (e) => { // Make sure the event trigger isn't a click event if (e.type === 'click' && e.button !== 0) { return; } // Make sure we don't currently have a setTimeout running // before starting another if (pressTimer === null) { pressTimer = setTimeout(() => { // Execute soemthing !!! }, 1000) } }
取消功能
這個(gè)函數(shù)基本上就是名字所說(shuō)的,取消了調(diào)用start函數(shù)時(shí)創(chuàng)建的setTimeout。
要取消setTimeout,我們將在javascript中使用 clearTimeout 方法,該方法基本上清除了使用setTimeout()設(shè)置的計(jì)時(shí)器方法。
在使用clearTimeout之前,我們首先需要檢查 pressTimer 變量是否設(shè)置為null。如果它未設(shè)置為null,則表示存在活動(dòng)計(jì)時(shí)器。所以,我們需要清除計(jì)時(shí)器,你猜對(duì)了,將 pressTimer 變量設(shè)置為 null 。
let cancel = (e) => { // Check if timer has a value or not if (pressTimer !== null) { clearTimeout(pressTimer) pressTimer = null } }
一旦 mouseup 事件被觸發(fā),就會(huì)調(diào)用此函數(shù)。
設(shè)置觸發(fā)器
剩下的就是將事件監(jiān)聽器添加到要添加長(zhǎng)按效果的按鈕上。
addEventListener("mousedown", start); addEventListener("click", cancel);
總而言之,我們有:
// Define variable let pressTimer = null; // Create timeout ( run function after 1s ) let start = (e) => { if (e.type === 'click' && e.button !== 0) { return; } if (pressTimer === null) { pressTimer = setTimeout(() => { // Execute something !!! }, 1000); } } // Cancel Timeout let cancel = (e) => { // Check if timer has a value or not if (pressTimer !== null) { clearTimeout(pressTimer); pressTimer = null; } } // select element with id longPressButton let el = document.getElementById('longPressButton'); // Add Event listeners el.addEventListener("mousedown", start); // Cancel timeouts if this events happen el.addEventListener("click", cancel); el.addEventListener("mouseout", cancel);
將它全部包裝在Vue指令中
在創(chuàng)建Vue指令時(shí),Vue允許我們?cè)诮M件的全局或本地定義指令,但在本文中我們將使用全局路由。
讓我們構(gòu)建完成此任務(wù)的指令。
首先,我們必須聲明自定義指令的名稱。
Vue.directive('longpress', { }
這基本上注冊(cè)了一個(gè)名為 v-longpress的全局自定義指令.
接下來(lái),我們使用一些參數(shù)添加bind hook函數(shù) ,這允許我們引用元素指令綁定,獲取傳遞給指令的值并標(biāo)識(shí)使用該指令的組件。
Vue.directive('longpress', { bind: function (el, binding, vNode) { } }
接下來(lái),我們?cè)赽ind函數(shù)中添加我們的長(zhǎng)按javascript代碼。
Vue.directive('longpress', { bind: function (el, binding, vNode) { // Define variable let pressTimer = null // Define funtion handlers // Create timeout ( run function after 1s ) let start = (e) => { if (e.type === 'click' && e.button !== 0) { return; } if (pressTimer === null) { pressTimer = setTimeout(() => { // Execute something !!! }, 1000) } } // Cancel Timeout let cancel = (e) => { // Check if timer has a value or not if (pressTimer !== null) { clearTimeout(pressTimer) pressTimer = null } } // Add Event listeners el.addEventListener("mousedown", start); // Cancel timeouts if this events happen el.addEventListener("click", cancel); el.addEventListener("mouseout", cancel); } })
接下來(lái),我們需要添加一個(gè)函數(shù)來(lái)運(yùn)行將傳遞給 longpress 指令的方法。
// Long Press vue directive Vue.directive('longpress', { bind: function (el, binding, vNode) { // Define variable let pressTimer = null // Define funtion handlers // Create timeout ( run function after 1s ) let start = (e) => { if (e.type === 'click' && e.button !== 0) { return; } if (pressTimer === null) { pressTimer = setTimeout(() => { // Execute function handler() }, 1000) } } // Cancel Timeout let cancel = (e) => { // Check if timer has a value or not if (pressTimer !== null) { clearTimeout(pressTimer) pressTimer = null } } // Run Function const handler = (e) => { // Execute method that is passed to the directive binding.value(e) } // Add Event listeners el.addEventListener("mousedown", start); // Cancel timeouts if this events happen el.addEventListener("click", cancel); el.addEventListener("mouseout", cancel); } })
現(xiàn)在我們可以在我們的Vue應(yīng)用程序中使用該指令,該指令將正常工作,直到用戶添加的值不是指令值中的函數(shù)。所以我們必須通過(guò)在發(fā)生這種情況時(shí)警告用戶來(lái)防止這種情況。
要警告用戶,我們將以下內(nèi)容添加到bind函數(shù):
// Make sure expression provided is a function if (typeof binding.value !== 'function') { // Fetch name of component const compName = vNode.context.name // pass warning to console let warn = `[longpress:] provided expression '${binding.expression}' is not a function, but has to be` if (compName) { warn += `Found in component '${compName}' ` } console.warn(warn) }
最后,這個(gè)指令也適用于觸控設(shè)備。所以我們?yōu)?touchstart , touchend & touchcancel 添加事件監(jiān)聽器。
把所有東西放在一起:
Vue.directive('longpress', { bind: function (el, binding, vNode) { // Make sure expression provided is a function if (typeof binding.value !== 'function') { // Fetch name of component const compName = vNode.context.name // pass warning to console let warn = `[longpress:] provided expression '${binding.expression}' is not a function, but has to be` if (compName) { warn += `Found in component '${compName}' ` } console.warn(warn) } // Define variable let pressTimer = null // Define funtion handlers // Create timeout ( run function after 1s ) let start = (e) => { if (e.type === 'click' && e.button !== 0) { return; } if (pressTimer === null) { pressTimer = setTimeout(() => { // Run function handler() }, 1000) } } // Cancel Timeout let cancel = (e) => { // Check if timer has a value or not if (pressTimer !== null) { clearTimeout(pressTimer) pressTimer = null } } // Run Function const handler = (e) => { binding.value(e) } // Add Event listeners el.addEventListener("mousedown", start); el.addEventListener("touchstart", start); // Cancel timeouts if this events happen el.addEventListener("click", cancel); el.addEventListener("mouseout", cancel); el.addEventListener("touchend", cancel); el.addEventListener("touchcancel", cancel); } })
現(xiàn)在引用我們的Vue組件:
<template> <div> <button v-longpress="incrementPlusTen" @click="incrementPlusOne">{{value}}</button> </div> </template> <script> export default { data() { return { value: 10 } }, methods: { // Increment value plus one incrementPlusOne() { this.value++ }, // increment value plus 10 incrementPlusTen() { this.value += 10 } } } </script>
如果您希望了解有關(guān)自定義指令的更多信息,可以使用的鉤子函數(shù),可以傳遞給此鉤子函數(shù)的參數(shù),函數(shù)縮寫。偉大的家伙@vuejs在解釋它這里方面做得很好。
成功 !!!
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Vue3+Vite實(shí)現(xiàn)動(dòng)態(tài)路由的詳細(xì)實(shí)例代碼
我們?cè)陂_發(fā)大型系統(tǒng)的時(shí)候一般都需要?jiǎng)討B(tài)添加路由,下面這篇文章主要給大家介紹了關(guān)于Vue3+Vite實(shí)現(xiàn)動(dòng)態(tài)路由的相關(guān)資料,文中通過(guò)圖文以及實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-08-08Vue實(shí)現(xiàn)內(nèi)部組件輪播切換效果的示例代碼
這篇文章主要介紹了Vue實(shí)現(xiàn)內(nèi)部組件輪播切換效果的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-04-04如何解決Element-ui的el-table固定列后出現(xiàn)的表格錯(cuò)位問題
這篇文章主要介紹了如何解決Element-ui的el-table固定列后出現(xiàn)的表格錯(cuò)位問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-09-09vue 取出v-for循環(huán)中的index值實(shí)例
今天小編就為大家分享一篇vue 取出v-for循環(huán)中的index值實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-11-11前端VUE雙語(yǔ)實(shí)現(xiàn)方案詳細(xì)教程
在項(xiàng)目需求中我們會(huì)遇到國(guó)際化的中英文切換,這篇文章主要給大家介紹了關(guān)于前端VUE雙語(yǔ)實(shí)現(xiàn)方案的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-08-08vue實(shí)現(xiàn)全選組件封裝實(shí)例詳解
這篇文章主要介紹了vue?全選組件封裝,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-02-02vue中前端如何實(shí)現(xiàn)pdf預(yù)覽功能(含vue-pdf插件用法)
這篇文章主要給大家介紹了vue中前端如何實(shí)現(xiàn)pdf預(yù)覽功能的相關(guān)資料,文中包含vue-pdf插件用法,在前端開發(fā)中,很多時(shí)候我們需要進(jìn)行pdf文件的預(yù)覽操作,需要的朋友可以參考下2023-07-07