如何区分单击事件和双击事件?

use*_*795 102 javascript jquery jquery-events

我有一个带有id的li按钮"my_id".我single click用这个元素附加了 事件

1.

$("#my_id").click(function() { 
    alert('single click');
});
Run Code Online (Sandbox Code Playgroud)

2.

$("#my_id").dblclick(function() {
    alert('double click');
});
Run Code Online (Sandbox Code Playgroud)

但每次它都给了我 "my_id"

Rya*_*yan 75

Quirksmodedblclick解释了事件的行为.

a的事件顺序dblclick是:

  1. 鼠标按下
  2. 鼠标松开
  3. 点击
  4. 鼠标按下
  5. 鼠标松开
  6. 点击
  7. DBLCLICK

此规则的一个例外是(当然)Internet Explorer的自定义顺序为:

  1. 鼠标按下
  2. 鼠标松开
  3. 点击
  4. 鼠标松开
  5. DBLCLICK

如您所见,在同一元素上同时监听这两个事件将导致对click处理程序的额外调用.

  • 当“event.detail”可用时,这是从单击处理程序检测双击的最佳方法。请参阅[此答案](/sf/answers/3775734161/)。 (2认同)

Adr*_*ler 61

您需要使用超时来检查第一次单击后是否有另一次单击.

这是诀窍:

// Author:  Jacek Becela
// Source:  http://gist.github.com/399624
// License: MIT

jQuery.fn.single_double_click = function(single_click_callback, double_click_callback, timeout) {
  return this.each(function(){
    var clicks = 0, self = this;
    jQuery(this).click(function(event){
      clicks++;
      if (clicks == 1) {
        setTimeout(function(){
          if(clicks == 1) {
            single_click_callback.call(self, event);
          } else {
            double_click_callback.call(self, event);
          }
          clicks = 0;
        }, timeout || 300);
      }
    });
  });
}
Run Code Online (Sandbox Code Playgroud)

用法:

$("button").single_double_click(function () {
  alert("Try double-clicking me!")
}, function () {
  alert("Double click detected, I'm hiding")
  $(this).hide()
})
Run Code Online (Sandbox Code Playgroud)
<button>Click Me!</button>
Run Code Online (Sandbox Code Playgroud)

编辑:

如下所述,更喜欢使用原生dblclick事件:http://www.quirksmode.org/dom/events/click.html

或者是jQuery提供的:http://api.jquery.com/dblclick/

  • 这似乎可以很好地工作,但是点击之间允许的延迟时间(两次点击被解释为双击)不同系统配置不同?依靠```dblclick```事件可能更安全 (14认同)
  • @AdrienSchuler - 从您链接的文档:*不建议将处理程序绑定到同一元素的click和dblclick事件.*问题是关于*both*. (14认同)

Ren*_*iot 23

一个简单的功能.不需要jquery或其他框架.将您的函数作为参数传递

<div onclick="doubleclick(this, function(){alert('single')}, function(){alert('double')})">click me</div>
    <script>
        function doubleclick(el, onsingle, ondouble) {
            if (el.getAttribute("data-dblclick") == null) {
                el.setAttribute("data-dblclick", 1);
                setTimeout(function () {
                    if (el.getAttribute("data-dblclick") == 1) {
                        onsingle();
                    }
                    el.removeAttribute("data-dblclick");
                }, 300);
            } else {
                el.removeAttribute("data-dblclick");
                ondouble();
            }
        }
    </script>
Run Code Online (Sandbox Code Playgroud)

  • 我认为这应该是最好的答案.但是,我必须将超时减少到200才能在Windows IE8上运行,但这个值可能是操作系统和用户相关的.并且还保存了计时​​器参考,以便在注册双击时取消执行点击. (2认同)

kyw*_*kyw 13

原来没有利用更多的即席状态和setTimeout,而是有一个本机属性detail,您可以从该event对象访问它!

element.onclick = event => {
   if (event.detail === 1) {
     // it was a single click
   } else if (event.detail === 2) {
     // it was a double click
   }
};
Run Code Online (Sandbox Code Playgroud)

现代浏览器甚至IE-9都支持它:)

来源:https : //developer.mozilla.org/en-US/docs/Web/API/UIEvent/detail

  • 只是一个可访问性说明:如果通过键盘触发单击事件(例如,当用户通过 Tab 键聚焦按钮并按 Enter 键时),则生成的事件的详细信息属性为 0,因此执行类似 `if(evt .detail !== 1) return;` 拒绝意外双击将阻止没有鼠标的用户访问该按钮。 (4认同)
  • 在双击的情况下,仍然会触发一次单击(其中“ event.detail === 1”)。参见我的[fiddle](https://jsfiddle.net/tsyrak/0y8uqemc/4/)或[对此线程的此评论](/sf/ask/61642591/在dblclick事件触发时触发#comment95729771_29993141)。 (2认同)
  • 您仍然需要在第一次单击时设置一个计时器才能不触发。检查下面我的答案/sf/ask/384795141/ Differentiate-single-click-event-and-double-click-event/60177326#60177326 (2认同)

小智 13

现代正确答案是接受的答案和@kyw 的解决方案之间的混合。您需要超时以防止第一次单击并event.detail检查以防止第二次单击。

const button = document.getElementById('button')
let timer
button.addEventListener('click', event => {
  if (event.detail === 1) {
    timer = setTimeout(() => {
      console.log('click')
    }, 200)
  }
})
button.addEventListener('dblclick', event => {
  clearTimeout(timer)
  console.log('dblclick')
})
Run Code Online (Sandbox Code Playgroud)
<button id="button">Click me</button>
Run Code Online (Sandbox Code Playgroud)


Álv*_*lez 12

我担心这种行为取决于浏览器:

将处理程序绑定到同一元素的click和dblclick事件是不可取的.触发的事件序列因浏览器而异,有些事件在dblclick之前接收到两个点击事件,而其他事件只接收一个事件.双击敏感度(双击检测到的点击之间的最长时间)可能因操作系统和浏览器而异,通常可由用户配置.

http://api.jquery.com/dblclick/

在Firefox中运行代码,click()处理程序中的alert()会阻止您再次单击.如果删除此类警报,则会同时获得这两个事件.

  • 当“event.detail”可用时,这是从单击处理程序检测双击的最佳方法。请参阅[此答案](/sf/answers/3775734161/)。 (2认同)

bra*_*ers 10

那么为了双击(单击两次),您必须先单击一次.该click()处理器触发你的第一次点击,而且由于警报弹出,你没有机会做第二次点击火的dblclick()处理程序.

更改处理程序以执行除a之外的操作alert(),您将看到该行为.(也许改变元素的背景颜色):

$("#my_id").click(function() { 
    $(this).css('backgroundColor', 'red')
});

$("#my_id").dblclick(function() {
    $(this).css('backgroundColor', 'green')
});
Run Code Online (Sandbox Code Playgroud)


A1r*_*Pun 6

这些答案都没有满足我的需求,所以我创建了一个灵感来自@AdrienSchuler发布的要点的解决方案.仅当您要将单击和双击绑定到元素时,才使用此解决方案.否则我建议使用本机clickdblclick听众.

这些是差异:

  • Vanillajs,没有依赖
  • 不要等待setTimeout处理click或doubleclick处理程序
  • 双击它时,首先触发单击处理程序,然后双击处理程序

使用Javascript:

function makeDoubleClick(doubleClickCallback, singleClickCallback) {
    var clicks = 0, timeout;
    return function() {
        clicks++;
        if (clicks == 1) {
            singleClickCallback && singleClickCallback.apply(this, arguments);
            timeout = setTimeout(function() { clicks = 0; }, 400);
        } else {
            timeout && clearTimeout(timeout);
            doubleClickCallback && doubleClickCallback.apply(this, arguments);
            clicks = 0;
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

用法:

var singleClick = function(){ console.log('single click') };
var doubleClick = function(){ console.log('double click') };
element.addEventListener('click', makeDoubleClick(doubleClick, singleClick));
Run Code Online (Sandbox Code Playgroud)

下面是jsfiddle中的用法,jQuery按钮是接受的答案的行为.

的jsfiddle

  • 上面的代码和小提琴的“ Vanilla”版本不起作用...这是固定的Vanilla版本:http://jsfiddle.net/jeum/cpbwx5vr/19/ (2认同)

Fab*_*ert 6

如何区分对同一个元素的单击和双击?

如果你并不需要将它们混合,你可以依靠clickdblclick每个将做的工作就好了。

尝试混合它们时会出现一个问题:一个dblclick事件实际上也会触发一个click事件,因此您需要确定单击是“独立”单击还是双击的一部分。

另外:你不应该在同一个元素上同时使用clickanddblclick

不建议将处理程序绑定到同一元素的 click 和 dblclick 事件。触发事件的顺序因浏览器而异,有些在 dblclick 之前收到两个点击事件,而其他只收到一个。双击灵敏度(被检测为双击的最大单击间隔时间)可能因操作系统和浏览器而异,并且通常是用户可配置的。
来源:https : //api.jquery.com/dblclick/

现在是好消息:

您可以使用事件的detail属性来检测与事件相关的点击次数。这使得双击内部click相当容易检测。

问题仍然是检测单击以及它们是否是双击的一部分。为此,我们又回到使用计时器和setTimeout.

将所有内容包装在一起,使用数据属性(以避免全局变量)并且无需自己计算点击次数,我们得到:

HTML:

<div class="clickit" style="font-size: 200%; margin: 2em; padding: 0.25em; background: orange;">Double click me</div>

<div id="log" style="background: #efefef;"></div>
Run Code Online (Sandbox Code Playgroud)

JavaScript:

<script>
var clickTimeoutID;
$( document ).ready(function() {

    $( '.clickit' ).click( function( event ) {

        if ( event.originalEvent.detail === 1 ) {
            $( '#log' ).append( '(Event:) Single click event received.<br>' );

            /** Is this a true single click or it it a single click that's part of a double click?
             * The only way to find out is to wait it for either a specific amount of time or the `dblclick` event.
             **/
            clickTimeoutID = window.setTimeout(
                    function() {
                        $( '#log' ).append( 'USER BEHAVIOR: Single click detected.<br><br>' );
                    },
                    500 // how much time users have to perform the second click in a double click -- see accessibility note below.
                );

        } else if ( event.originalEvent.detail === 2 ) {
            $( '#log' ).append( '(Event:) Double click event received.<br>' );
            $( '#log' ).append( 'USER BEHAVIOR: Double click detected.<br>' );
            window.clearTimeout( clickTimeoutID ); // it's a dblclick, so cancel the single click behavior.
        } // triple, quadruple, etc. clicks are ignored.

    });

});
</script>
Run Code Online (Sandbox Code Playgroud)

演示:

JSfiddle


关于可访问性和双击速度的说明:

  • 正如维基百科所说,“连续两次点击被解释为双击所需的最大延迟没有标准化。”
  • 无法在浏览器中检测系统的双击速度。
  • 似乎默认值为 500 毫秒,Windows 上的范围为 100-900 毫米(来源
  • 想想那些在操作系统设置中将双击速度设置为最慢的残疾人。
    • 如果系统双击速度慢于我们上面默认的 500 毫秒,则单击和双击行为都会被触发。
    • 要么不要使用依赖组合单击和双击一个和相同的项目。
    • 或者:在选项中添加一个设置以具有增加值的能力。

花了一段时间才找到满意的解决方案,我希望这会有所帮助!


jeu*_*eum 5

另一个基于A1rPun答案的简单Vanilla解决方案(参见对jQuery解决方案的小提琴,两者都在这一个).

似乎在用户双击时不触发单击处理程序,单击处理程序必然在延迟后触发...

var single = function(e){console.log('single')},
    double = function(e){console.log('double')};

var makeDoubleClick = function(e) {

  var clicks = 0,
      timeout;

  return function (e) {

    clicks++;

    if (clicks == 1) {
      timeout = setTimeout(function () {
        single(e);
        clicks = 0;
      }, 250);
    } else {
      clearTimeout(timeout);
      double(e);
      clicks = 0;
    }
  };
}
document.getElementById('btnVanilla').addEventListener('click', makeDoubleClick(), false);
Run Code Online (Sandbox Code Playgroud)

  • 如果你不想点击单击,这确实是最好的选择:) (3认同)

nex*_*nex 5

这是用于任意数量事件的jeum代码的替代方案:

 var multiClickHandler = function (handlers, delay) {
    var clicks = 0, timeout, delay = delay || 250;
    return function (e) {
      clicks++;
      clearTimeout(timeout);
      timeout = setTimeout(function () {
        if(handlers[clicks]) handlers[clicks](e);
        clicks = 0;
      }, delay);
    };
  }

  cy.on('click', 'node', multiClickHandler({
    1: function(e){console.log('single clicked ', e.cyTarget.id())},
    2: function(e){console.log('double clicked ', e.cyTarget.id())},
    3: function(e){console.log('triple clicked ', e.cyTarget.id())},
    4: function(e){console.log('quadro clicked ', e.cyTarget.id())},
    // ...
  }, 300));
Run Code Online (Sandbox Code Playgroud)

需要这个用于cytoscape.js应用程序。