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);
(完)