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

您是否曾想过按住按钮几秒钟才能在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在解释它这里方面做得很好。

成功 !!!

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

(0)

相关推荐

  • vue自定义移动端touch事件之点击、滑动、长按事件

    用法: **HTML** <div id="app" class="box" v-tap="vuetouch" //vuetouch为函数名,如没有参数,可直接写函数名 v-longtap="{fn:vuetouch,name:'长按'}" //如果有参数以对象形式传,fn 为函数名 v-swipeleft="{fn:vuetouch,name:'左滑'}" v-swiperight="{f

  • VUE长按事件需求详解

    在开发中常常会有长按事件的需求,这里我简单的介绍几种长按事件的需求. 需求一:长按数字累加或者累减 HTML: <div class="mui-numbox" data-numbox-step='10' data-numbox-min='0' data-numbox-max='100'> <button class="mui-btn mui-numbox-btn-minus" type="button"@touchstart=&

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

    您是否曾想过按住按钮几秒钟才能在Vue应用程序中执行某个功能? 您是否曾想在应用程序上创建一个按钮,通过按一次(或按住按钮的整个输入)来清除单个输入? 如果你曾有过这些想法,很好,我也是.那么恭喜你看到了这篇文章. 本文将解释如何通过按下(或按住)按钮来执行功能和删除输入. 首先,我将解释如何在VanillaJS中实现这一目标.然后,为它创建一个Vue指令. 那么,让我们开始吧. 原理 为了实现长按,用户需要按住按钮几秒钟. 要在代码中复制它,我们需要在按下鼠标"单击"按钮时监听,启动

  • 详解如何在vue+element-ui的项目中封装dialog组件

    1.问题起源 由于 Vue 基于组件化的设计,得益于这个思想,我们在 Vue 的项目中可以通过封装组件提高代码的复用性.根据我目前的使用心得,知道 Vue 拆分组件至少有两个优点: 1.代码复用. 2.代码拆分 在基于 element-ui 开发的项目中,可能我们要写出一个类似的调度弹窗功能,很容易编写出以下代码: <template> <div> <el-dialog :visible.sync="cnMapVisible">我是中国地图的弹窗&l

  • 详解如何在Vue中动态添加类名

    目录 静态和动态类 有条件的类名 使用数组语法 使用对象语法 与自定义组件一起使用 快速生成类名 使用计算属性来简化类 能够向组件添加动态类名是非常强大的功能.它使我们可以更轻松地编写自定义主题,根据组件的状态添加类,还可以编写依赖于样式的组件的不同变体. 添加动态类名与在组件中添加 prop :class="classname"一样简单.无论classname的计算结果是什么,都将是添加到组件中的类名. 当然,对于Vue中的动态类,我们可以做的还有很多.在本文中,我们将讨论很多内容:

  • 详解如何在vue项目中使用layui框架及采坑

    根据官网的文档,要在一个html文件下使用layui里面的组件库其实很简单,但是在vue项目中使用该ui库却存在着很多坑,下面我们就详细讲解一下如何在vue-cli搭建的项目下使用layui 1.第一个坑:vue项目中使用npm安装引入时报错(目前并没有找到引入的合适的方式,知道的可以留言探讨) 在官网中我们可以看到他提到支持npm安装,但是当我们安装成功后,在main.js中引入时却报并不能找到该模块的错. 所以,我们先下载文件包,然后在html文件中用link和script标签的方式引入 2

  • 详解如何在Vue项目中导出Excel

    Excel 导出 Excel 的导入导出都是依赖于js-xlsx来实现的. 在 js-xlsx的基础上又封装了Export2Excel.js来方便导出数据. 使用 由于 Export2Excel不仅依赖js-xlsx还依赖file-saver和script-loader. 所以你先需要安装如下命令: npm install xlsx file-saver -S npm install script-loader -S -D 由于js-xlsx体积还是很大的,导出功能也不是一个非常常用的功能,所以

  • 详解如何在vue项目中引入elementUI组件

    前提:已经安装好Vue 初始化vue vue init webpack itemname 运行初始化demo 运行一下初始后的demo,如果没有问题则进行安装elementUI npm run dev 安装 elementUI npm i element-ui -S 引入elementUI 在main.js中引入elementUI import ElementUI from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' Vu

  • 详解如何在 vue 项目里正确地引用 jquery 和 jquery-ui的插件

    使用vue-cli构建的vue项目,webpack的配置文件是分散在很多地方的,而我们需要修改的是build/webpack.base.conf.js,修改两处的代码 // 在开头引入webpack,后面的plugins那里需要 var webpack = require('webpack') // resolve module.exports = { // 其他代码... resolve: { extensions: ['', '.js', '.vue'], fallback: [path.j

  • 详解如何在Vue项目中发送jsonp请求

    起因 公司临时要支撑河南的一个项目,做一个单点登录的功能. 简单来说,就是以下3步 客户方点击某个按钮进入我们的页面a 在页面a中由前端发送一个jsonp请求到客户方,得到一个token值 前端得到token值后向自己后端发送一个请求,后端根据token去redis(token的值就是redis里的key)里取值(key=token的值,value=用户信息等)判断用户是否已登陆,若登陆则根据取到的工号等信息后端模拟登陆,若没有登陆,则跳转到客户方登陆页面 怎么做 发送jsonp请求,axios

  • 详解如何在vue中使用sass

    创建一个基于 webpack 模板的新项目 全局安装 vue-cli $ npm install --global vue-cli 创建一个基于 webpack 模板的新项目 $ vue init webpack my-project 安装依赖 $ cd my-project $ npm install 为了使用sass,我们需要安装sass的依赖包 npm install --save-dev sass-loader //sass-loader依赖于node-sass npm install

  • 详解如何在vue项目中使用lodop打印插件

    项目中使用到打印的功能.领导推荐使用Lodop Lodop是什么东东,反正就是可以定制打印的插件... 既然是插件,vue的渐进式开发.完全可以拿来化为己用. 如何使用那?先大概看了下开发文档,就是一堆demo,一个js文件,三个安装程序,我擦,这么简单.come on 电脑安装C-Lodop,就可以打印预览来了. 开工,翻来覆去就一个LodopFuncs.js是干货,扔到项目中.就差怎么调里面的方法了. 如何引用,当然得改造喽 LodopFuncs.js 方法改造如下 //====判断是否需要

随机推荐