vue实现按钮长按功能:添加自定义指令+ 自定义指令中调用 method 中的方法+指令获取data里面的值

在这里插入图片描述

原来的遥控是采用按键形式,但是说是用户体验不好,但是虚拟摇杆又没有搞定,这里采用第二种方案,增加按钮长按功能,但是用的elementUI里面又没有提供长按功能的button,网上找的方案是自定义vue指令,关键是通过定时器实现长按功能:(为了便于理解,我把原文步骤都放过来,最后提供我修改后的完整代码,原文链接在最后)
原理如下:
长按,即用户按下按钮并持续按住几秒钟,即触发长按功能。那么,要实现这样的功能关键点在于我们需要知道的是用户什么时候按下按钮和什么时候松开按钮。幸运的是:浏览器在当用户点击鼠标时提供给了我们两个事件: mousedown 和 mouseup。当用户按下鼠标时会触发 mousedown 事件,用户松开鼠标时会触发 mouseup 事件。有了这两个事件,我们只需这样做:

1.当mousedown 事件触发时,启动一个计时器,开始计时。

2.设定一个时间阈值,比如2秒。在时间阈值内如果 mouseup 事件被触发了,即认为这是一次普通的单击,不执行长按功能函数并清除定时器。反之,超出时间阈值后 mouseup 事件才被触发,即认为用户在长按按钮,此时执行长按功能函数。

实现:
1、计时器变量
首先,我们定义一个变量timer,用于存储定时器,并且设置初始值为null;

let timer = null

2、启动函数
该函数是当浏览器监听到mousedown事件触发后执行的回调函数,该函数主要作用是创建并启动定时器,并且在设定的时间阈值内如果mouseup还未触发,则执行长按功能函数。函数代码如下:

var start = function (e) {
        // 如果是点击事件,不启动计时器,直接返回
        if (e.type === 'click'){
            return
        }
        if (timer == null){
            // 创建定时器 ( 2s之后执行长按功能函数 )
            timer = setTimeout(function () {
                //执行长按功能函数
                longFunc()
            },2000)
        }
    }

3、取消函数
该函数是当浏览器监听到mouseup事件触发后执行的回调函数,该函数主要作用是清除定时器。函数代码如下:

var cancel = function () {
        if (timer !== null){
            clearTimeout(timer)
            timer = null
        }
    }

4、设置事件监听器
设置事件监听器,用于监听mousedown、mouseup和click事件,分别执行不同的回调函数。

// 添加事件监听器

el.addEventListener("mousedown", start);

// 长按事件取消,取消计时器

el.addEventListener("click", cancel);

el.addEventListener("mouseout", cancel);

5、定义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表示传递给指令的值,详细请参考官方文档自定义指令

6、使用指令
到这里,我们就可以在模板中愉快的使用指令啦。

<!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>

以上就是原文所有步骤了,上面就是一个单html页面,但是项目用的脚手架搭建、,下面我展示我的代码
从上往下来看:页面
在这里插入图片描述
首先为前进后退四个按钮绑定btnNum这个值,为1,2,3,4,再绑定长按指令 v-longpress=“incrementPlusTen”

在script里面,首先要引入vue:import Vue from 'vue';
在这里插入图片描述
不然会报错 Vue is not defined
在这里插入图片描述
在data里面初始化value值为10,btnNum为0;
在这里插入图片描述
在methods里面增加方法:(incrementPlusOne这个我没用到)
在这里插入图片描述
script最后是长按指令:

//长按指令
Vue.directive('longpress', 
   { bind:function (el, binding, vnode){
            var timer = null;
            var myVar =null;
            var start = function (e) {
                // 如果是点击事件,不启动计时器,直接返回
                if (e.type === 'click'){
                    return
                }
                if (timer == null){
                    // 创建定时器 ( 2s之后执行长按功能函数 )
                    timer = setTimeout(function () {
                        //执行长按功能函数
                        myVar = setInterval(function(){vnode.context.remoteCon(el.getAttribute("btnNum"),this.roId); }, 2000);
                        binding.value(e)
                    },2000)
                }
            }
            var cancel = function () {
                if (timer !== null){
                    clearTimeout(timer)
                    timer = null
                    
                    clearInterval(myVar);
                }
            }

            // 添加事件监听器
            el.addEventListener("mousedown", start);

            // 取消计时器
            el.addEventListener("click", cancel);
            el.addEventListener("mouseout", cancel);
    }
    })

这里我主要是增加了自己的长按功能函数,这个长按我是要调用remoteCon这个函数来发送相应的指令,我在它本身的setTimeout定时器里面嵌套了setInterval定时器,

两种定时器区别:

setInterval(表达式,时间):页面载入后,每经过指定毫秒值后执行指定表达式,是间隔多次执行的
setTimeout(表达式,时间):页面载入后,经过指定毫秒值后执行指定表达式,只执行一次

remoteCon是 method 中的方法,直接使用会报错,
在这里插入图片描述
在指令后面加参数vnode,通过vnode.context.remoteCon();就可以使用methods中的方法,

remoteCon(num,roId),其中两个参数,一个是按钮属性,1,2,3,4对应前进后退,roId对应机器人id,其中可以使用this.roId获取机器人id,但是始终无法获取num的值,(说是可以通过 binding.value(e)获取值,但是我没搞明白)所以通过一开始定义过btnNum这个值,用el.getAttribute("btnNum")来获取
在这里插入图片描述
另外我还发现,按照原博主的代码,在执行长按方法时候,start会执行四次,导致后面调用方法都是四次一调,四次一调,这里我修改了一下,在start的function前面加了bind:如下图,反括号加在末尾
在这里插入图片描述

长按效果 第一个参数为方向键绑定的num,第二个为机器人id:
在这里插入图片描述

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Vue3使用TypeScript获取动态组件component实例调用里面组件的方法,可以先通过 `ref` 获取动态组件的实例,再通过 `as` 关键字将其转换为具体的子组件类型,从而调用子组件方法。 例如,假设有一个动态组件 `MyComponent`,其包含了一个子组件 `ChildComponent`,并且我们需要在父组件获取 `ChildComponent` 实例并调用方法。可以使用如下代码: ```vue <template> <div> <component :is="selectedComponent" ref="myComponent"></component> <button @click="handleClick">Call Child's Method</button> </div> </template> <script lang="ts"> import { defineComponent, ref } from 'vue' import ChildComponent from './ChildComponent.vue' export default defineComponent({ components: { ChildComponent }, data() { return { selectedComponent: 'ChildComponent' } }, setup() { const myComponentRef = ref<MyComponent | null>(null) const handleClick = () => { const childComponent = myComponentRef.value?.$refs.child as ChildComponent if (childComponent) { childComponent.doSomething() } } return { myComponentRef, handleClick } } }) </script> ``` 在上面的代码,我们使用 `ref` 将动态组件 `MyComponent` 的实例绑定到 `myComponentRef` 变量上,并使用 `as` 关键字将其类型转换为 `MyComponent | null`。然后,在 `handleClick` 方法,我们通过 `myComponentRef.value?.$refs.child` 获取到子组件 `ChildComponent` 的实例,并将其类型转换为 `ChildComponent`。最后,我们就可以调用 `ChildComponent` 方法了。 需要注意的是,在模板使用 `ref` 时,需要添加一个 `.value` 后缀来访问 `ref` 变量所引用的对象。例如,上面的代码,我们通过 `myComponentRef.value?.$refs.child` 来获取子组件 `ChildComponent` 的实例。 另外,如果子组件方法需要访问子组件的数据或者方法,可以使用 `provide` 和 `inject` 方法实现。具体使用方法可以参考 Vue3 官方文档。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值