问题描述
开发过程中需要实现部分元素的自由拖拽效果,但是实现后存在一个问题:当鼠标移动过快,会造成鼠标跑出元素外从而导致拖拽失效。
// 原代码
onMouseDown(e, flag) {
// ...
// 拖拽
function onMouseMove(e) {
moveAt(e.pageX, e.pageY); // 移动元素
}
target.addEventListener('mousemove', onMouseMove);
// 放开
function onMouseUp(e) {
target.removeEventListener('mousemove', onMouseMove);
}
target.addEventListener('mouseup', onMouseUp);
}
问题分析
根据上网查询相关资料,结合个人分析,得到问题原因如下:鼠标移动过快,导致 mousemove 事件频繁触发,相应的事件处理函数也频繁调用,引起延迟。延迟过后由于元素的移动速度不及鼠标的移动速度,造成鼠标移动到元素外,从而触发 mouseout 事件,提前结束拖拽。
解决方法
将事件处理函数添加到 document 上,而非目标元素上,让 mousemove 事件在有延迟的情况下仍然可以被响应即可。
// 修改后代码
onMouseDown(e, flag) {
// ...
// 拖拽
function onMouseMove(e) {
moveAt(e.pageX, e.pageY); // 移动元素
}
document.addEventListener('mousemove', onMouseMove);
// 放开
function onMouseUp(e) {
document.removeEventListener('mousemove', onMouseMove);
}
target.addEventListener('mouseup', onMouseUp);
}
补充
将事件绑定到 document 和 body 上的区别在于:绑定到 document 上,当鼠标移动到菜单栏(边界)上,元素仍然可以拖动,而 body 则无效。
参考文档
原文地址
【个人博客】