听取双击而非单击

15

我想知道为什么当我双击一个元素时,click事件会被触发?

我有这段代码: (JSBIN)

HTML

<p id="hello">Hello World</p>

JavaScript

document.getElementById('hello').addEventListener('click', function(e){
  e.preventDefault();
  this.style.background = 'red';
}, false);
document.getElementById('hello').addEventListener('dbclick', function(){
  this.style.background = 'yellow';
}, false);

它应该对单击和双击执行不同的操作,但似乎当你双击 p 时它会提前捕获 click 事件并忽略双击。

我尝试了阻止 click 事件,但它似乎仍然无法监听到只有 dblclick 的事件。如何只监听 dblclick

更新

我的代码中有个错字,dbclick 是错误的,应该是 dblclick。但问题仍然存在,当用户双击时仍然触发了 click 事件。

这是更新后的代码,证明了这一点:(JSBin)

document.getElementById('hello').addEventListener('click', function(e){
  e.preventDefault();
  this.style.background = 'red';
  this.innerText = "Hello World clicked";
}, false);
document.getElementById('hello').addEventListener('dblclick', function(){
  this.style.background = 'green';
}, false); 

1
你的意思应该是 dblclick - Lightness Races in Orbit
这个问题是因为打错字而产生的。我希望我能删除它! - Mohsen
1
为什么?!答案中提出了一些其他重要的观点。请不要因为您打错字而忽略给出的建议。修正拼写错误并不能解决“如何仅侦听dblclick”的问题。 - Lightness Races in Orbit
@TomalakGeret'kal,你是对的!我更新了问题。 - Mohsen
@TomalakGeret'kal,你认为stopPropagation会对这里有帮助吗? - Mohsen
不行。在click事件中做任何事情都不能改变后续是否会发生dblclick事件的结果,除非调用一个神奇的时间旅行函数。我的答案已经很全面了,抱歉。 - Lightness Races in Orbit
6个回答

20

dblclick不是神奇的: 尽管第二次快速的 click 触发了 dblclick 事件,但第一次的 click 已经触发了自己的事件处理程序。

你几乎永远不应该在DOM元素上同时设置 clickdblclick 事件; 如果这样做,你需要使用计时器等花哨的技巧来缓解问题。

在这种特定情况下,你还需要修复你的拼写错误 (s/dbclick/dblclick/) 才能使事件正常触发。

另请注意,dblclick 实际上并不是 DOM 规范的一部分(在DOM Level 2 1.6.2中不存在)。因此,它被称为“DOM Level 0”功能。


我在一些简单的情况下使用这两种方式都没有问题,例如,单击表示用户已选择列表中的某个项目,因此可以显示有关该项目的更多信息和/或启用相关按钮,而双击则表示自动单击相关按钮。 - nnnnnn
@nnnnnn:在那种情况下,双重选择可能对用户来说是透明的。对于OP的特定情况可能也是如此,但这并不是普遍规律。 - Lightness Races in Orbit
+1,然后进入JSBIN并将“dbclick”更正为“dblclick”,它会按照我的预期进行操作:从单击事件变为红色,然后从双击事件变为黄色。 - Stephen P

13

'dbclick'更改为'dblclick'


5

请使用dblclick代替dbclick


3

为了回答这个修订后的问题(如何处理点击和双击事件时的互斥),您需要延迟点击事件,直到不再可能发生双击事件。这会导致略微的延迟(例如500毫秒)来处理单击,但否则DOM无法预测是否会出现第二个单击事件。

这里有一个示例脚本:https://dev59.com/lHNA5IYBdhLWcg3wpfmu#11057483


2
这对我有效(使用d3库,但d也可以是字典对象):
function log(s){try{console.log(s)}catch(e){}} // for debugging

var click_d = null

function click(d){
    log("click")
    click_d = d
    setTimeout(click_action, 200)
}

function click_action(){
    log("click_action")
    if(click_d == null){
        log("aborted")
        return
    }
    d = click_d

    // do things with d
}

function doubleclick(d){
    log("dblclick")
    click_d = null

    // do things with d
}

-3

我猜你的电脑速度比较慢。在速度较慢的电脑上,双击可能会被解释为两次单击,时间间隔相当长。你可以尝试调整鼠标设置并更改双击设置来解决问题。如果你的电脑真的很快,没有延迟问题,那么你的问题可能出在其他地方。如果不是电脑速度慢造成的问题,那么双击被视为单击的可能性非常小(就像你发布的代码错误)。问题可能出在其他地方。


-1:执行时间并不是特别重要的,除了它的存在;您仍将至少获得初始的“click”事件。在这里进行负投票可能有点严厉,但我认为可以假定OP知道他的计算机上双击的感觉。 - Lightness Races in Orbit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接