最近做了自己的开源项目 Msw-Tools,参考了 VConsole 工具中按钮的拖拽功能,计划给 MSW 按钮也增加类似的拖拽效果,并兼容PC端和手机端,但是遇到一个问题:一个按钮绑定了多个事件,怎样才能阻止 mousemove 或 touchmove 与 click 事件同时触发

一、背景

如上图所示,实现 MSW 按钮拖拽要用到 mousedown、mousemove、mouseup 事件,对应的移动端要用到 touchstart、touchmove、touchend 事件,但是按钮上已经绑定了 click 点击事件,所以就要想办法阻止 mouse 鼠标事件或 touch 触摸事件 与 click 事件同时触发。不然每次拖拽按钮后都会触发 click 事件,这显然是不友好的。

二、问题解析

事件的执行顺序依次是:mousedown > mousemove > mouseup > click,因此,要想 mouseup 事件执行完后,不执行 click 事件,可能不太好直接处理,但是可以间接的实现。设置一个 移动状态的开关,并加上 延迟处理 就可以达到"阻止 click 事件"的目的。

三、代码实现

因为 Msw-Tools 工具是使用 Svelte 框架开发的,所以这里展示 Svelte 部分代码。

<!-- msw.svelte --><div class="msw-container"><div on:click|stopPropagation={showModal}bind:this={btnDOM}class="msw-show">MSW</div>
</div><script>import { onMount } from "svelte";// 区分当前是PC端,还是移动端,来设置 mouse 事件 或 touch 事件function getModels() {let userAgentInfo = navigator.userAgent;let mobileAgents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];return mobileAgents.reduce((prev, ua)=>{return userAgentInfo.includes(ua) || prev}, false)};const MSW_BTN_POSITION = '__MSW_BTN_POSITION__'let show = false;let btnDOM = null;let isDrop = false;let isMoving = false;let offset = {x: 0,y: 0,};let offsetDown = {};let dropTimer = null;let isMobile = getModels();let btnW = 0;let btnH = 0;let clientW = 0;let clientH = 0;let eventType = isMobile ? 'touchstart' : 'mousedown';// DOM 挂载后执行onMount(async () => {// 初始化,获取按钮、视口宽高、计算边界值initClientData();return () => {// component 卸载后,解除事件绑定btnDOM.removeEventListener(eventType, btnMousedown)}});function initClientData() {// 按钮位置保存在本地,可以记住位置,避免每次去拖拽let local = localStorage.getItem(MSW_BTN_POSITION)if (local) {offset = JSON.parse(local)btnMove()}let w = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidthclientW = isMobile ? w : document.body.clientWidthclientH = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeightbtnW = btnDOM.offsetWidthbtnH = btnDOM.offsetHeight// 给按钮绑定 mousedown 或 touchstart 事件btnDOM.addEventListener(eventType, btnMousedown)}function eventHandle (type) {if (isMobile) {document[`${type}EventListener`]('touchmove', mousemove);document[`${type}EventListener`]('touchend', mouseup);} else {document[`${type}EventListener`]('mousemove', mousemove);document[`${type}EventListener`]('mouseup', mouseup);}}function showModal () {if (!isMoving) {show = true;}}function btnMousedown(e) {e = e || window.eventisDrop = trueoffsetDown = {...getOffset(e)};eventHandle('add')}function mousemove(e) {e = e || window.eventif (isDrop) {let data = getOffset(e);// 判断是否移动了isMoving = !(offsetDown.x === data.x && offsetDown.y === data.y)let x = data.x - btnW / 2;let y = data.y - btnH / 2;if (x > 5 && x < (clientW-btnW - 5)) {offset.x = x;}if (y > 5 &&  y < (clientH-btnH - 5)) {offset.y = y;}if (isMoving) {btnMove()}clearTimeout(dropTimer);dropTimer = setTimeout(()=>{isMoving = false;clearTimeout(dropTimer);dropTimer = null;}, 300);}}function mouseup() {if (isDrop) {window.localStorage.setItem(MSW_BTN_POSITION, JSON.stringify(offset))eventHandle('remove')}isDrop = false// console.log('mouseup')}function btnMove (){btnDOM.style.cssText = `left: ${offset.x}px;top: ${offset.y}px;right: auto;bottom: auto;`}function getOffset(e) {return isMobile ? {x: e.targetTouches[0].clientX,y: e.targetTouches[0].clientY,} : {x: e.clientX,y: e.clientY,}}
</script><style lang="scss" type="text/scss">@import "index";
</style>
  • 效果体验:msw-tools

欢迎访问:天问博客

阻止 mousemove 或 touchmove 与 click 事件同时触发相关推荐

  1. 阻止移动端 touchmove 与 scroll 事件冲突

    在移动端开发过程中,如果要实现一个元素或按钮的拖动定位,会出现很多坑.例如:元素上下移动过程中,会触发 body 的 scroll 事件,导致整体的位置偏移,这时就需要 阻止移动端 touchmove ...

  2. 移动端的click事件延迟触发的原理是什么?如何解决这个问题?

    移动端的click事件延迟触发的原理是什么?如何解决这个问题? 原理 :移动端屏幕双击会缩放页面 300ms延迟 会出现点透现象 在列表页面上创建一个弹出层,弹出层有个关闭的按钮,你点了这个按钮关闭弹 ...

  3. wap开发问题总结(ios中click事件无法触发、身份证分隔、倒计时、验证码分隔等)

    需求背景:用户在通过短信验证码方式注册或者登陆时,存在二次卡场景(运营商回收原机主不用的手机号,存放三个月后,再次开放给新机主),导致新机主可以登录原机主账号,如果原机主不换绑手机.二次卡判断条件:手 ...

  4. jquery 动态生成html后click事件不触发原因

    转自:http://www.iam3y.com/html/560.html 最近在做一个项目的时候,遇到动态加载微博内容,然后点击"展开评论"后获取该微博的所有评论.这里使用了动态 ...

  5. click和touchmove vue_移动端touch事件影响click事件以及在touchmove添加preventDefault导致页面无法滚动的解决方法...

    这两天自己在写一个手机网页,用到了触屏滑动的特效,就是往右滑动的时候左侧隐藏的菜单从左边划出来. 做完之后在手机原生浏览器中运行正常,但在QQ和微信中打开,发现touchmove只会触发一次,而且to ...

  6. click事件在什么时候出发_超全的js事件机制amp;事件委托

    超全的js事件机制&事件委托,想要理解js事件只需认真看完此篇即可~ 目录结构: 什么是事件机制 事件冒泡事件捕获 DOM事件流事件委托 误区 在同一个对象上注册事件,并不一定按照注册顺序执行 ...

  7. el-table click事件多次触发_JavaScript从零开始——DOM事件编程(1)

    事件的本质是程序各个组成部分之间的一种通信方式,也是异步编程的一种实现.DOM 支持大量的事件,本章开始,我们一起看看 DOM 的事件编程. 1 概念 DOM 的事件操作(监听和触发),都定义在Eve ...

  8. blur事件和ajax,js关于blur事件阻塞click事件

    出现场景: 页面有一个输入框A绑定了blur事件,且这个事件里面需要用到ajax请求数据,然后有一个按钮B绑定了点击事件: 在A里面输入完信息后, 还没失去焦点的时候点击B,这个时候发现只执行了A的b ...

  9. 搜索提示时jquery的focusout和click事件冲突问题完美解决

    在主流的搜索引擎上搜索时,输入内容,往往会弹出智能提示.输入框为input,智能提示区域为suggest.接下来一般有两种操作: 1.选择某一提示,则把内容复制到input中,自动关闭suggest: ...

最新文章

  1. 2020年第五届中国通用人工智能年会
  2. C++智能指针简单剖析
  3. 【推荐一位Python大佬】 从程序员到创业者,再到自由职业
  4. 新概念英语第二册课文电子版_新概念英语第二册课文学生(Victoria)朗读
  5. java微信学习 接入
  6. mysql中的union用法以及子查询综合应用
  7. 算法完成了如何开发服务端API?
  8. python源代码被解释器转换后的格式_python源代码被解释器转换后的格式是什么?...
  9. winform 打印快递电子面单_电子面单接口说明文档-(附C#源码)
  10. 从DOS中装操作系统时要加载smartdrv命令
  11. maya显示已安装_安装cad2010显示已安装怎么办?峰哥教你怎么解决
  12. python3 打字小游戏
  13. Windows操作系统及其应用
  14. CNCC2022将于12月重磅开启,聚焦算力、数据、生态三大主题
  15. linux卡在黑白进度条界面,linux启动画面、进度条问题
  16. PHP通过CURL上传图片(微信公众号上传素材)
  17. 最新C#/CLR的访谈录( 访Peter Hallam)
  18. 魅族手机MX4 MX4 Pro 魅蓝note 无法连接USB调试,adb连不上问题的解决方案
  19. vue+element ui+腾讯云开发打造会员管理系统之实战教程(三)系统登录
  20. Unity2021发布微信小游戏步骤(附带工具和源码)

热门文章

  1. 20110805 组队赛 f题
  2. E+H差压变送器FMD78
  3. 华为手机桌面计算机怎么恢复出厂设置密码,华为手机恢复出厂设置密码多少呢?...
  4. MSDN webcast《Silverlight for Windows Phone开发》系列视频第二季
  5. Android WorkManager★★★
  6. 数据压缩实验七——MEPG音频编码
  7. Android模拟器使用SD卡
  8. 微信无法连接服务器1-104,全局错误码
  9. linux 创建用户命令
  10. 图像的基本知识123