文章目录
- 问题描述
- 常规解决方案(不完美)
- 最终解决方案
- 小结
问题描述
javascript中经常会碰到同一个目标元素同时绑定了click和dblclick事件。当触发双击事件的时候,就会出现触发了2次click事件和1次dblclick事件。这显然不是我们想要的结果。
例如:
<script>
const handleClick = (e) => {
console.log("触发了单击事件,e=", e);
};
const handleDblClick = (e) => {
console.log("触发了双击击事件,e=", e);
};
</script>
<button ondblclick="handleDblClick(event)" onclick="handleClick(event)">点击</button>
如果没有任何处理,双击button就会出现两次单击和一次双击事件的触发。如下图:
常规解决方案(不完美)
百度了一下,大部分都是使用setTimeout对单击事件做延时处理。当触发双击事件的时候,清除单击事件中的定时器,从而实现只触发双击事件的逻辑
例如:
<script>
var clickFlag = null;//是否点击标识(定时器编号)
function doOnClick(e) {
if (clickFlag) {//取消上次延时未执行的方法
clickFlag = clearTimeout(clickFlag);
}
clickFlag = setTimeout(function () {
console.log("触发了单击事件,e=", e);
}, 300);//延时300毫秒执行
}
function doOnDblClick(e) {
if (clickFlag) {//取消上次延时未执行的方法
clickFlag = clearTimeout(clickFlag);
}
console.log("触发了双击击事件,e=", e);
}
</script>
<button ondblclick="doOnDblClick(event)" onclick="doOnClick(event)">点击</button>
以上代码看似可以解决这个问题,但实际上当双击间隔>300ms&&<500ms时,还是额外会触发一次单击事件。经过测试双击间隔最长可以达到500ms。如果将上述代码中的300改为500,那么单击事件的延迟过高(想要触发单击事件,要等到点击后500ms才会执行,用户体验太差了)。
最终解决方案
最终决定在单击事件中做文章,通过判断单击事件间隔来判断触发单击事件还是双击事件
例如:
<script>
let times = 0;//计时器时间内,点击次数
let timer = null;//计时器
const handleClick = e => {
times++
if (timer) return;
timer = setTimeout(() => {
if (times === 1) {
click(e)
} else {
dblClick(e)
}
times = 0;
clearTimeout(timer)
timer = null
}, 200)
}
const click = (e) => {
console.log("触发了单击事件,e=", e);
};
const dblClick = (e) => {
console.log("触发了双击击事件,e=", e);
};
</script>
<button onclick="handleClick(event)">点击</button>
通过以上代码,就可以定义在规定计时器时间内(200ms)单击次数,如果只有一次那就是单击事件,超过1次就按照双击事件处理。
小结
依靠浏览器本身的双击事件很难解决这个问题(只有当单击定时器时间>=500ms时才能避免同时触发单击和双击事件),利用时间段内产生的单击事件次数就可以很好的定义和区分开单击和双击事件了