本文探讨在Web开发中同时绑定click和dblclick事件时产生的冲突问题。由于双击会触发两次单击,导致业务逻辑混乱。文章通过分析事件触发顺序,提出利用setTimeout延迟执行单击逻辑并结合clearTimeout取消的解决方案,并指出该方案受系统双击速度设置影响的局限性。
问题背景
情况描述
当某个元素,例如div,同时绑定了click事件和dblclick事件,且这两个事件需要处理相对独立的业务逻辑时,即单击时不触发双击逻辑,双击时不触发单击逻辑,就会遇到冲突。在实际测试中发现,执行双击操作时,总会额外触发一次单击事件。下文旨在解决这一问题。
情况分析
首先需要明确click和dblclick的执行顺序,测试过程省略,测试结果如下:
click:mousedown -- mouseup -- click
dblclick:mousedown -- mouseup -- click -- mousedown -- mouseup -- click -- dblclick
由此可见,在触发dblclick之前,实际上已经执行了两次click事件,而第一次的click会被屏蔽(具体原因尚不明确)。
解决方案与实现
解决方案
首先考虑是否可以停止事件传播,但发现浏览器并未提供相应方法,若自行实现难度较大,因为单击事件关联的行为必须支持取消操作。
因此考虑采用延迟策略,这也是目前想到的唯一解决办法。利用setTimeout()来延迟执行click事件的处理逻辑,然后在需要屏蔽单击时,通过clearTimeout()来取消该延迟任务。
具体代码
代码如下:
var test = (function(){
var clickText = 'click<br>';
var dblclickText = 'dblclick<br>';
var timer = null;
return {
click: function(){
clearTimeout(timer);
timer = setTimeout(function(){
$('body').append(clickText);
}, 300);
},
dblclick: function(){
clearTimeout(timer);
$('body').append(dblclickText);
},
init: function(){
$(function(){
$('div').click(test.click).dblclick(test.dblclick);
});
}
}
})();
test.init(); html代码
代码如下:
<div style="width:100px;height:100px;background:red;text-align:center;line-height:33px;-moz-user-select:none;-khtml-user-select:none;user-select:none">click<br>or<br>dblclick</div> 方案局限性
后续
文章标题已说明这是不完美解决方案,因为在Windows系统中,控制面板允许调整鼠标的双击速度(其他系统情况不明)。如果将系统设置的双击速度调得较慢,上述demo将失效。因此,300毫秒只是一个大致数值。
作者:胡尐睿