您是否曾想过按住按钮几秒钟才能在Vue应用程序中执行某个功能?javascript
您是否曾想在应用程序上建立一个按钮,经过按一次(或按住按钮的整个输入)来清除单个输入?html
若是你曾有过这些想法,很好,我也是。那么恭喜你看到了这篇文章。前端
本文将解释如何经过按下(或按住)按钮来执行功能和删除输入。vue
首先,我将解释如何在VanillaJS中实现这一目标。而后,为它建立一个Vue指令。java
那么,让咱们开始吧。git
为了实现长按,用户须要按住按钮几秒钟。github
要在代码中复制它,咱们须要在按下鼠标“单击”按钮时监听,启动计时器,无论咱们但愿用户在执行函数以前按住按钮,并在时间设置以后执行该功能。express
很是简单!可是,咱们须要知道用户什么时候按住该按钮。浏览器
当用户单击按钮时,在单击事件以前会触发另外两个事件: mousedown 和 mouseup 。网络
当用户按下鼠标按钮时会调用 mousedown 事件,而当用户释放该按钮时会调用mouseup事件。
咱们须要作的就是:
发生mousedown事件后启动计时器。
清除该计时器,而且在2secs标记以前触发mouseup事件后不执行该函数。即完整点击事件。
只要计时器在到达那个时间以前没有被清除,咱们就会发现mouseup事件没有被触发 - 咱们能够说用户没有释放按钮。所以,它被认为是长按,而后咱们能够继续执行所述功能。
让咱们深刻研究代码并完成这项工做。
首先,咱们必须定义3件事,即:
variable 用于存储计时器。
start 函数启动计时器。
cancel 函数取消定时器
这个变量基本上保存了setTimeout的值,因此咱们能够在发生mouseup事件时取消它。
let pressTimer = null;
咱们将变量设置为null,这样咱们就能够检查变量,以便知道当前是否有一个活动定时器,而后才能取消它。
该函数由setTimeout组成,它基本上是Javascript中的一种方法,它容许咱们在函数中声明的特定持续时间以后执行函数。
请记住,在建立click事件的过程当中,会触发两个事件。但咱们须要启动计时器的是mousedown事件。所以,若是是单击事件,咱们不须要启动计时器。
// 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) } }
这个函数基本上就是名字所说的,取消了调用start函数时建立的setTimeout。
要取消setTimeout,咱们将在javascript中使用 clearTimeout 方法,该方法基本上清除了使用setTimeout()设置的计时器方法。
在使用clearTimeout以前,咱们首先须要检查 pressTimer 变量是否设置为null。若是它未设置为null,则表示存在活动计时器。因此,咱们须要清除计时器,你猜对了,将 pressTimer 变量设置为 null 。
let cancel = (e) => { // Check if timer has a value or not if (pressTimer !== null) { clearTimeout(pressTimer) pressTimer = null } }
一旦 mouseup 事件被触发,就会调用此函数。
剩下的就是将事件监听器添加到要添加长按效果的按钮上。
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指令时,Vue容许咱们在组件的全局或本地定义指令,但在本文中咱们将使用全局路由。
让咱们构建完成此任务的指令。
首先,咱们必须声明自定义指令的名称。
Vue.directive('longpress', { }
这基本上注册了一个名为 v-longpress的全局自定义指令.
接下来,咱们使用一些参数添加bind hook函数 ,这容许咱们引用元素指令绑定,获取传递给指令的值并标识使用该指令的组件。
Vue.directive('longpress', { bind: function (el, binding, vNode) { } }
接下来,咱们在bind函数中添加咱们的长按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); } })
接下来,咱们须要添加一个函数来运行将传递给 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); } })
如今咱们能够在咱们的Vue应用程序中使用该指令,该指令将正常工做,直到用户添加的值不是指令值中的函数。因此咱们必须经过在发生这种状况时警告用户来防止这种状况。
要警告用户,咱们将如下内容添加到bind函数:
// 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) }
最后,这个指令也适用于触控设备。因此咱们为 touchstart , touchend & touchcancel 添加事件监听器。
把全部东西放在一块儿:
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); } })
如今引用咱们的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>
若是您但愿了解有关自定义指令的更多信息,可使用的钩子函数,能够传递给此钩子函数的参数,函数缩写。伟大的家伙@vuejs在解释它这里方面作得很好。
成功 !!!
LogRocket是一个前端日志记录工具,可以让您像在本身的浏览器中同样重放问题。LogRocket不是猜想错误发生的缘由,也不是要求用户提供屏幕截图和日志转储,而是让您重播会话以快速了解出现了什么问题。它适用于任何应用程序,不管框架如何,而且具备从Redux,Vuex和@ngrx / store记录其余上下文的插件。
除了记录Redux操做和状态以外,LogRocket还记录控制台日志,JavaScript错误,堆栈跟踪,带有标题+正文的网络请求/响应,浏览器元数据和自定义日志。它还使用DOM来记录页面上的HTML和CSS,从新建立即便是最复杂的单页应用程序的像素完美视频。
附:代码示范来源