详解如何在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 相关文章推荐
日期函数扩展类Ver0.1.1
Sep 07 Javascript
js正则表达式replace替换变量方法
May 21 Javascript
jQuery ajax中使用confirm,确认是否删除的简单实例
Jun 17 Javascript
基于jQuery的ajax方法封装
Jul 14 Javascript
很实用的js选项卡切换效果
Aug 12 Javascript
js时间查询插件使用详解
Apr 07 Javascript
js实现单张图片平移切换效果
Oct 11 Javascript
bootstrap paginator分页插件的两种使用方式实例详解
Nov 14 Javascript
Node中使用ES6语法的基础教程
Jan 05 Javascript
jQuery对底部导航进行跳转并高亮显示的实例代码
Apr 23 jQuery
简单了解Javscript中兄弟ifream的方法调用
Jun 17 Javascript
从0搭建vue-cli4脚手架
Jun 17 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中自定义函数dump查看数组信息类似var_dump
2014/01/27 PHP
PHP批量去除BOM头代码分享
2015/06/26 PHP
Yii使用DeleteAll连表删除出现报错问题的解决方法
2016/07/14 PHP
thinkPHP多语言切换设置方法详解
2016/11/11 PHP
PHP面向对象五大原则之里氏替换原则(LSP)详解
2018/04/08 PHP
确保Laravel网站不会被嵌入到其他站点中的方法
2019/10/18 PHP
javascript实现的网页局布刷新效果
2008/12/01 Javascript
JavaScript 学习笔记(十一)
2010/01/19 Javascript
javascript中自定义对象的属性方法分享
2013/07/12 Javascript
使用JavaScript和C#中获得referer
2014/11/14 Javascript
js实现文本框只允许输入数字并限制数字大小的方法
2015/08/19 Javascript
基于JS2Image实现圣诞树代码
2015/12/24 Javascript
详解Vue.js——60分钟组件快速入门(上篇)
2016/12/05 Javascript
jQuery的extend方法【三种】
2016/12/14 Javascript
JS得到当前时间的方法示例
2017/03/24 Javascript
axios 处理 302 状态码的解决方法
2018/04/10 Javascript
解决vue中监听input只能输入数字及英文或者其他情况的问题
2018/08/30 Javascript
jQuery+css last-child实现选择最后一个子元素操作示例
2018/12/10 jQuery
vue实现分页栏效果
2019/06/28 Javascript
js使用文件流下载csv文件的实现方法
2019/07/15 Javascript
vue 路由懒加载中给 Webpack Chunks 命名的方法
2020/04/24 Javascript
解决Vue中的生命周期beforeDestory不触发的问题
2020/07/21 Javascript
python生成器,可迭代对象,迭代器区别和联系
2018/02/04 Python
python实现创建新列表和新字典,并使元素及键值对全部变成小写
2019/01/15 Python
python使用adbapi实现MySQL数据库的异步存储
2019/03/19 Python
python ChainMap 合并字典的实现步骤
2019/06/11 Python
Python多进程编程常用方法解析
2020/03/26 Python
Python实现Excel自动分组合并单元格
2021/02/22 Python
美国最便宜的旅游网站:CheapTickets
2017/07/09 全球购物
Paradox London官方网站:英国新娘鞋婚礼鞋品牌
2019/08/29 全球购物
中专毕业个人的自荐信格式
2013/09/21 职场文书
我的长生果教学反思
2014/04/28 职场文书
英语教师个人工作总结
2015/02/09 职场文书
2015年清剿火患专项行动工作总结
2015/07/27 职场文书
python geopandas读取、创建shapefile文件的方法
2021/06/29 Python
MySQL系列之十五 MySQL常用配置和性能压力测试
2021/07/02 MySQL