vue 节流、拖拽指令

请叫我海龟先生
• 阅读 1181

1、在开发中时长遇到按钮重复点击或者多次点击的情况

比如创建订单或者其他情况,当然也可以通过设置变量开关,禁止状态,这里就分享一个 节流的指令

VUE3好像指令的生命周期和组件的生命周期同步了
//立即执行版本,点击后会执行一次,然后进入定时器
export const throttle = {
    inserted: function(el, binding) {
        let timer = null
        el.addEventListener('click', handClick, false)
        function handClick() {
            if (timer) {
                return
            }
            // 当指令传参时 
            let arg = binding.arg
            binding.value(arg)
            timer = setTimeout(() => {
                clearTimeout(timer)
                timer = null
            }, 2000)
        }
        el._handClick_ = handClick
    },
    unbind: function(el) {
        //销毁时 清除事件
        if (el._handClick_) {
            el.removeEventListener('click', el._handClick_, false)
            el._handClick_ = null
            delete el._handClick_
        }
    }
}

2、使用 注册就不写了

<div v-throttle:1="toHandle" ></div>
    v-throttle:1 是传了个参数,当然可以不传 v-throttle="toHandle"
    v-throttle="toHandle(1)",这种写法是绑定了个表达式,不是函数

2、拖拽指令

export const drag = {
    inserted: function(el, binding) {
        const willChange = getComputedStyle(el).willChange
        const position = getComputedStyle(el).position
        const transform = getComputedStyle(el).transform

        // 盒子宽高
        let width = el.offsetWidth
        let height = el.offsetHeight

        // 设备 宽高 getPageX,getPageY 为设备宽高
        let pageWidth = getPageX()
        let pageHeight = getPageY()
        // 记录手指按下位置
        let dX,dY

        if (['absolute', 'fixed'].indexOf(position) === -1) {
            el.style.position = 'absolute'
        }

        el.style.willChange =
        willChange === 'auto' ? 'left,top' : `${willChange},left,top`

          el.style.transform =
        transform === 'none' ? 'translateZ(0)' : `${transform} translateZ(0)`

        function start(e) {
            let box = el.getBoundingClientRect()
            let touchMsg = e.changedTouches[0]
            dX = touchMsg.pageX - box.left
            dY = touchMsg.pageY - box.top

            el.addEventListener('touchmove',move, false)
            el.addEventListener('touchcancel',cancel, false)
        }

        function move(eMove) {
            let moveMsg = eMove.changedTouches[0]
            let top = moveMsg.pageY - dY
            let left = moveMsg.pageX - dX
            // 边界值限定
            let maxLeft = pageWidth - width
            let maxTop = pageHeight - height

            el.style.top =  top > maxTop ? maxTop + 'px' : (top > 1 ? top + 'px' : '0px')
            el.style.left = left > maxLeft ? maxLeft + 'px' : (left > 1 ? left + 'px' : '0px')

            eMove.preventDefault()
        }
        function cancel() {
            el.removeEventListener('touchstart',start, false)
            el.removeEventListener('touchmove',move, false)
            el.removeEventListener('touchcancel',cancel, false)
        }

        el.addEventListener('touchstart',start,false)
        el.__dragTouchstartHandler__ = start
    },
    unbind: function(el) {
        if (el.__dragTouchstartHandler__) {
            el.removeEventListener('touchstart', el.__dragTouchstartHandler__, false)
            el.__dragTouchstartHandler__ = null
            delete el.__dragTouchstartHandler__
        }

    }
}

整体思路: 1、移动端并没有手指按下点到父元素的距离(offsetTop),只有距离页面的 X,Y,所以 用按下点到页面的距离 - 元素距离顶部距离 = 按下点到父元素距离 2、移动时、用移动点位距离 - 按下点到父元素距离 = 定位位置 3、最后 preventDefault()阻止默认行为 4、后面就是指令解绑了

点赞
收藏
评论区
推荐文章
秃头王路飞 秃头王路飞
6天前
webpack5手撸vue2脚手架
webpack5手撸vue相信工作个12年的小伙伴们在面试的时候多多少少怕被问到关于webpack方面的知识,本菜鸟最近闲来无事,就尝试了手撸了下vue2的脚手架,第一次发帖实在是没有经验,望海涵。 language JavaScript "name": "vuecliversion2", "version": "1.0.0", "desc
Jacquelyn38 Jacquelyn38
1年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。 1、使用解构获取json数据let jsonData   id: 1, status: "OK", data: ['a', 'b'] ; let  id, status, data: number   jsonData; console.log(id, status, number )
blmius blmius
1年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录 问题 用navicat导入数据时,报错: 原因这是因为当前的MySQL不支持datetime为0的情况。 解决修改sql\mode: sql\mode:SQL Mode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。 全局s
小森森 小森森
6天前
校园表白墙微信小程序V1.0 SayLove -基于微信云开发-一键快速搭建,开箱即用
后续会继续更新,敬请期待2.0全新版本 欢迎添加左边的微信一起探讨!项目地址:](https://www.aliyun.com/activity/daily/bestoffer?userCodesskuuw5n) \2. Bug修复更新日历 2. 情侣脸功能大家不要使用了,现在阿里云的接口已经要收费了(土豪请随意), \ \ 和 注意
Peter20 Peter20
1年前
mysql中like用法
like 的通配符有两种%(百分号):代表零个、一个或者多个字符。\(下划线):代表一个数字或者字符。1\. name以"李"开头where name like '李%' 2\. name中包含"云",“云”可以在任何位置where name like '%云%' 3\. 第二个和第三个字符是0的值where salary like '\00%' 4\
Karen110 Karen110
1年前
一篇文章带你了解JavaScript日期
日期对象允许您使用日期(年、月、日、小时、分钟、秒和毫秒)。一、JavaScript的日期格式一个JavaScript日期可以写为一个字符串:Thu Feb 02 2019 09:59:51 GMT+0800 (中国标准时间)或者是一个数字:1486000791164写数字的日期,指定的毫秒数自1970年1月1日00:00:00到现在。 1\. 显示日期使用
Stella981 Stella981
11个月前
Android So动态加载 优雅实现与原理分析
> 背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载. ![](https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png) 点击上方“蓝字”关注我
Wesley13 Wesley13
11个月前
MySql的优化步骤
MySql优化的一般步骤: **1.通过show status 命令了解各种sql的执行效率**   SHOW STATUS提供msyql服务器的状态信息   一般情况下,我们只需要了解以”Com”开头的指令   show session status like ‘Com%’:显示当前的连接的统计结果   show global status li
Stella981 Stella981
11个月前
Docker 部署SpringBoot项目不香吗?
  公众号改版后文章乱序推荐,希望你可以点击上方“**Java进阶架构师**”,点击右上角,将我们设为**★**“**星标**”!这样才不会错过每日进阶架构文章呀。   ![](http://dingyue.ws.126.net/2020/0920/b00fbfc7j00qgy5xy002kd200qo00hsg00it00cj.jpg)   **2
helloworld_34035044 helloworld_34035044
2个月前
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。 uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid() 或 uuid(sep)参数说明:sep 布尔值,生成的uuid中是否包含分隔符'',缺省为