关于 JS 拖拽功能的冲突问题及解决方法
前言
我在之前写过关于 JS 拖拽的文章,实现方式和网上能搜到的方法大致相同,别无二致,但是在一次偶然的测试中发现,这种绑定事件的方式可能会和其它的拖拽事件产生冲突,由此产生了对于事件绑定的思考。本文主要介绍解决这种冲突的方法,其实就是事件绑定的时机问题。
问题来源
这个问题是在类似如下 CodePen 例子中发现的,在有拖拽功能的页面中添加一个原生 input range 元素,可以发现 input range 的拖拽失效了。
See the Pen drag with conflict issue by Zongbin (@nzbin) on CodePen.
让我们看一下拖拽方法代码:
var draggable = function(modal, handle) {
...
$(handle).on('mousedown', dragStart);
$(document).on('mousemove', dragMove);
$(document).on('mouseup', dragEnd);
}
几乎网上的大部分拖拽案例都是上面这种绑定事件的方法。起初以为是 jQuery 事件绑定的问题,其实完全不相关,使用原生 JS 同样会遇到这种问题。
再看一下拖拽的事件绑定,很明显,在 document 上绑定的事件和 input range 的拖拽事件冲突了。其实,document 作为最上层的节点,它上面不应该绑定其它事件(事件代理除外),如果绑定,必须是临时性绑定,否则一定会造成冲突。
解决方法
知道问题所在之后,解决方法也非常简单,其中参考了 jQuery UI 的处理方式。
我们可以在拖拽开始的时候绑定 document 的事件,然后在拖拽结束的时候移除 document 的事件。
var draggable = function(modal, handle) {
...
var dragStart = function(e) {
...
$(document).on('mousemove', dragMove)
.on('mouseup', dragEnd);
}
...
var dragEnd = function(e) {
$(document).off('mousemove')
.off('mouseup');
...
}
$(handle).on('mousedown', dragStart);
}
下面 CodePen 中的 input range 已经可以正常拖动了。
See the Pen drag with conflict issue fixed by Zongbin (@nzbin) on CodePen.
总结
我们可以通过控制台的 Event Listener 查看绑定的事件,在平时的工作中,切记不要污染全局的默认事件。一般情况下,工作中并不会遇到本文所说的这一情况,但是如果真的碰到了,需要知道问题的所在。
关于 JS 拖拽功能的冲突问题及解决方法的更多相关文章
- 原生js拖拽功能制作滑动条实例教程
拖拽属于前端常见的功能,很多效果都会用到js的拖拽功能.滑动条的核心功能也就是使用js拖拽滑块来修改位置.一个完整的滑动条包括 滑动条.滑动痕迹.滑块.文本 等元素,先把html代码写出来,如下所示: ...
- 关于js拖拽功能,拖拽元素的position:fixed;left:0;right:0;样式引起左右拖动元素会出现落后鼠标移动距离的问题
被拖拽元素的样式如果为:position:fixed;left:0;right:0;(当时是为了让fixed定位的元素水平居中加的left:0;right:0;避免js动态计算定位的麻烦)时左右拖动会 ...
- chrome无法拖拽离线安装CRX格式插件解决方法
原文:http://chromecj.com/utilities/2018-09/1525.html 摘要 : chrome 67版本后无法拖拽离线安装CRX格式插件的解决方法 有一部分网友反映子 ...
- 通过 JS 实现简单的拖拽功能并且可以在特定元素上禁止拖拽
前言 关于讲解 JS 的拖拽功能的文章数不胜数,我确实没有必要大费周章再写一篇重复的文章来吸引眼球.本文的重点是讲解如何在某些特定的元素上禁止拖拽.这是我在编写插件时遇到的问题,其实很多插件的拖拽功能 ...
- Js元素拖拽功能实现
Js元素拖拽功能实现 需要解决的问题 最近项目遇到了一个问题,就是用户某个操作需要弹出一个自定义的内容输入框,但是有个缺点,当浏览太大的时候没办法点击确认和取消按钮,应为这个弹出框是采用绝对定位的,取 ...
- vuejs2.0使用Sortable.js实现的拖拽功能
简介 在使用vue1.x之前的版本的时候,页面中的拖拽功能,我在项目中是直接用的jquery ui中的sortable.js,只是在拖拽完成后,在update的回调函数中又重新排序了存放数据的数组.但 ...
- vue2.0使用Sortable.js实现的拖拽功能
简介 在使用vue1.x之前的版本的时候,页面中的拖拽功能,我在项目中是直接用的jQuery ui中的sortable.js,只是在拖拽完成后,在update的回调函数中又重新排序了存放数据的数组.但 ...
- js进阶 12-17 jquery实现鼠标左键按下拖拽功能
js进阶 12-17 jquery实现鼠标左键按下拖拽功能 一.总结 一句话总结:监听的对象必须是文档,鼠标按下运行mousemove事件,鼠标松开取消mousemove事件的绑定,div的偏移的话是 ...
- (Demo分享)利用JavaScript(JS)实现一个九宫格拖拽功能
利用JavaScript(JS)实现一个九宫格拖拽功能 Demo实现了对任意方格进行拖拽,可以交换位置,其中Demo-1利用了勾股定理判断距离! Demo-1整体思路: 1.首先div实现自由移动 ...
随机推荐
- bootstrap简单图文环绕效果
一. 下载bootstrap-3.3.7 二. 在html页面引入css,js; eg: <link src="bootstrap-3.3.7-dist/css/b ...
- MySql优化子查询
用子查询语句来影响子查询中产生结果rows的数量和顺序. For example: SELECT * FROM t1 WHERE t1.column1 IN (SELECT column1 FROM ...
- linux workqueue的名字长度小问题
在排查一个nvme的的workqueue的问题的时候,发现nvme的queue的进程名被截断了, [root@localhost caq]# ps -ef |grep -i nvme root : ? ...
- 如何在同一台机器上安装多个MySQL的实例
转自:'http://www.cnblogs.com/shangzekai/p/4375271.html 最近由于工作的需要,需要在同一台机器上搭建两个MySQL的实例,(注:已经存在了一个3306的 ...
- video.js不能控制本地视频或者音频播放时长
问题: 把视频放到本地,然后对视频进行测试,想要控制视频或者音频的播放时长,没办法做到,每次拉动进度条,都会使得本地视频重新播放 原因: 所有浏览器默认js无法访问本地地址,也就是说js不能对本地文件 ...
- mysql存储过程且mybatis调用
首先,需要执行符DELIMITER ,建议用//,即在存储过程开始前定义delimiter //,在结束后加上//,最后加上DELIMITER ; 具体原因@参考文章1写的很清楚,不再赘述. 参考文章 ...
- Linux Shell 编程语法
原文地址:http://www.cnblogs.com/fhefh/archive/2011/04/13/2014967.html.感谢作者的无私分享 编写代码 在计划好要程序干什么以及如何使用程序的 ...
- Log4net使用详细说明
1.概述 log4net是.Net下一个非常优秀的开源日志记录组件.log4net记录日志的功能非常强大.它可以将日志分不同的等级,以不同的格式,输出到不同的媒介.本文主要是介绍如何在Visual S ...
- [译] Linux吃掉了我的内存
英文原文: https://www.linuxatemyram.com/ 作者: Vidar Holen 译者: thinkam 发生了什么? Linux正借用你未使用的内存来做磁盘缓存.这使你的计算 ...
- openvpn的搭建
openvpn搭建 原创不易,转载请注明 openvpn简介 1.1 openvpn原理 OpenVpn的技术核心是虚拟网卡,其次是SSL协议实现 虚拟网卡是使用网络底层编程技术实现的一个驱动软件,安 ...