在一个元素既有拖拽事件,又有单击事件的时候,会发现每一次拖拽后都会触发元素的单击事件,所以我们得在拖拽事件的时候屏蔽掉元素的单击事件所绑定的方法。元素拖拽和单击事件触发的顺序是mosuedown,mousemove,mouseup,click,所以就需要针对这个事件顺序在拖拽的时候屏蔽单击事件。主要有以下三种方法来在拖拽事件中屏蔽掉单击事件的执行:
1、监听mousemove事件,在mousemove中加状态,在click事件中监听该状态
var elIsMove = false; //定义状态
//拖拽事件
element.onmousedown = function (evt) {
document.onmousemove = function (evt) { //实时改变目标元素element的位置
elIsMove = true; //在元素移动的时候改变状态
}
//停止拖动
document.onmouseup = function () {
document.onmousemove = null;
document.onmouseup = null;
}
}
//click事件
element.onclick = function (e) {
if (elIsMove) {
elIsMove = false; //如果状态是true,则证明元素被移动过,不触发click调用的方法
return;
}
}
2、监听鼠标按下的时间,超过150ms则为拖拽,否则为单击(该方案有弊端,如果操作过慢的用户,会一直不触发单击的方法,150ms差是查看别人的,觉得可以用,也测试过,但是我也不知道150从何而来)
var timer = 0; //定义时差变量
//拖拽事件
element.onmousedown = function (evt) {
var startTime = performance.now(); //记录初始时间
document.onmousemove = function (evt) { //实时改变目标元素element的位置
}
//停止拖动
document.onmouseup = function () {
timer = startTime - performance.now(); //计算按下和弹起时差
}
}
//click事件
element.onclick = function (e) {
if (timer && timer > 150) { //判断时差确定为单击还是拖拽
timer = 0;
return;
}
}
3、监听元素位置的前后变化,移动则为拖拽,不移动则为单击(个人认为该方法最靠谱)
var startLeft = 0, //定义位置初始变量
startTop = 0;
//拖拽事件
element.onmousedown = function (e) {
startLeft = e.clientX; //记录初始位置
startTop = e.clientY;
document.onmousemove = function (evt) { //实时改变目标元素element的位置
}
//停止拖动
document.onmouseup = function () {
}
}
//click事件
element.onclick = function (e) {
if (e.clientX !== startLeft || e.clientY !== startTop) {
startLeft = 0, //位置发生变化为拖拽
startTop = 0;
return;
}
}
上述就是在拖拽后屏蔽单击调用方法的三种方案,个人觉得对比位置变化是最合适的。