详解如何在Vue里建立长按指令


Posted in Javascript onAugust 20, 2018

您是否曾想过按住按钮几秒钟才能在Vue应用程序中执行某个功能?

您是否曾想在应用程序上创建一个按钮,通过按一次(或按住按钮的整个输入)来清除单个输入?

如果你曾有过这些想法,很好,我也是。那么恭喜你看到了这篇文章。

本文将解释如何通过按下(或按住)按钮来执行功能和删除输入。

首先,我将解释如何在VanillaJS中实现这一目标。然后,为它创建一个Vue指令。

那么,让我们开始吧。

原理

为了实现长按,用户需要按住按钮几秒钟。

要在代码中复制它,我们需要在按下鼠标“单击”按钮时监听,启动计时器,不管我们希望用户在执行函数之前按住按钮,并在时间设置之后执行该功能。

非常简单!但是,我们需要知道用户何时按住该按钮。

怎么做

当用户单击按钮时,在单击事件之前会触发另外两个事件: 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允许我们在组件的全局或本地定义指令,但在本文中我们将使用全局路由。

让我们构建完成此任务的指令。

首先,我们必须声明自定义指令的名称。

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在解释它这里方面做得很好。

成功 !!!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jQuery对象[0]是什么含义?
Jul 31 Javascript
js局部刷新页面时间具体实现
Jul 04 Javascript
Jquery解析Json格式数据过程代码
Oct 17 Javascript
JS实现控制表格只显示行边框或者只显示列边框的方法
Mar 31 Javascript
jQuery实现鼠标经过弹出提示信息的地图热点效果
Aug 07 Javascript
Javascrip实现文字跳动特效
Nov 27 Javascript
手机移动端实现 jquery和HTML5 Canvas的幸运大奖盘特效
Dec 06 Javascript
JS点击缩略图整屏居中放大图片效果
Jul 04 Javascript
老生常谈JavaScript面向对象基础与this指向问题
Oct 16 Javascript
五步轻松实现zTree的使用
Nov 01 Javascript
详解使用WebPack搭建React开发环境
Aug 06 Javascript
js判断非127开头的IP地址的实例代码
Jan 05 Javascript
微信小程序scroll-view实现滚动穿透和阻止滚动的方法
Aug 20 #Javascript
Angular6 写一个简单的Select组件示例
Aug 20 #Javascript
Layer弹出层动态获取数据的方法
Aug 20 #Javascript
layui 给数据表格加序号的方法
Aug 20 #Javascript
解决LayUI表单获取不到data的问题
Aug 20 #Javascript
Layui数据表格之获取表格中所有的数据方法
Aug 20 #Javascript
解决layui上传文件提示上传异常,实际文件已经上传成功的问题
Aug 19 #Javascript
You might like
php中使用array_filter()函数过滤空数组的实现代码
2014/08/19 PHP
分享最受欢迎的5款PHP框架
2014/11/27 PHP
php简单实现发送带附件的邮件
2015/06/10 PHP
php文件压缩之PHPZip类用法实例
2015/06/18 PHP
基于php数组中的索引数组和关联数组详解
2018/03/12 PHP
PHP检测一个数组有没有定义的方法步骤
2019/07/20 PHP
js压缩利器
2007/02/20 Javascript
不用写JS也能使用EXTJS视频演示
2008/12/29 Javascript
js 分页全选或反选标识实现代码
2011/08/09 Javascript
jQuery 设置 CSS 属性示例介绍
2014/01/16 Javascript
extjs每个组件要设置唯一的ID否则会出错
2014/06/15 Javascript
jquery序列化表单以及回调函数的使用示例
2014/07/02 Javascript
nodejs实现获取当前url地址及url各种参数值
2015/06/25 NodeJs
详解JS-- 浮点数运算处理
2016/11/28 Javascript
利用node.js实现自动生成前端项目组件的方法详解
2017/07/12 Javascript
vue实现树形菜单效果
2018/03/19 Javascript
vue实现验证码按钮倒计时功能
2018/04/10 Javascript
js隐式转换的知识实例讲解
2018/09/28 Javascript
微信小程序实现动态列表项的顺序加载动画
2019/07/25 Javascript
ES6函数实现排它两种写法解析
2020/05/13 Javascript
基于element-ui封装可搜索的懒加载tree组件的实现
2020/05/22 Javascript
Vue 的 v-model用法实例
2020/11/23 Vue.js
浅谈Python中copy()方法的使用
2015/05/21 Python
Python数组遍历的简单实现方法小结
2016/04/27 Python
python 通过 socket 发送文件的实例代码
2018/08/14 Python
Python3 JSON编码解码方法详解
2019/09/06 Python
Python入门基础之数字字符串与列表
2021/02/01 Python
2019年Java 最常见的 面试题
2016/10/19 面试题
自主招生自荐信范文
2013/12/04 职场文书
运动会邀请函范文
2014/01/31 职场文书
学雷锋标兵事迹材料
2014/08/18 职场文书
广告业务员岗位职责
2015/02/13 职场文书
公司放假通知怎么写
2015/04/15 职场文书
红与黑读书笔记
2015/06/29 职场文书
2015年重阳节主持词
2015/07/04 职场文书
Vue组件更新数据v-model不生效的解决
2022/04/02 Vue.js