给一个元素同时绑定click和dbclick存在的问题

这是一个我面试的面试题

代码实例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>demo</title>
</head>
<body>

    <button id="my_btn">click it</button>

<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
<script type="text/javascript">
    $("#my_btn").click(function() { 
        alert('single click');
    });

    $("#my_btn").dblclick(function() {
        alert('double click');
    });
</script>
</body>
</html>

运行上面的代码我们会发现不论我们怎么单击按钮都无法出现弹出框显示内容为‘double click’

我在面试时遇到这个问题,由于时间有限我想到了用定时器来解决,用一个状态值标志着出发了一次还是两次。现在回想当时的面试感觉回答的还是漏洞百出。

解决方案

我在stackflow中找到了这样一个解决方案

先贴个代码:

// 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);
      }
    });
  });
}

这个代码的实现跟我的思路相同,但是在stackflow中并未找到兼容大部分浏览器的方案,这个代码 在chrome,safari,FF,opera上没多大问题,存在比较明显的问题就是IE,ie<9不支持

访问http://gist.github.com/399624有正宗的解释(访问这个链接需要翻墙)

IE兼容性处理

$(this).bind("dblclick", function(event) {
    clicks = 2;
    double_click_callback.call(self, event);
});
$(this).bind("click", function(event) {
    setTimeout(function() {
        if (clicks != 2) {
            single_click_callback.call(self, event);
        }
        clicks = 0;
    }, timeout || 300);
});

由于在ie<9中click 和 dbclick的触发判断时间更短,会造成dbclick失效的问题,测试连续出发三次会出现想要dbclick的效果,所以需要将代码改成上面的实现格式,同时也会出现现弹出两个弹出框第一个内容为‘double click’, 第二个内容为‘single click’。

依然存在的问题

根据该连接上提供的解决方案,判断浏览器的类型和版本的代码发现还是有问题,你会发现结果无法执行,【IE兼容性处理】中我们提到过click和dbclick的判断时间很短,用上面的代码判断浏览器的类型和版本存在问题,不能执行,所以提供了如下的解决方案

(window.ActiveXObject && parseInt(navigator.appVersion.split(";")[1].replace(/[ ]/g, "").replace("MSIE","")) < 9)

根据浏览器的特有对象来判定浏览器的类型是个不错的方法

javascript原生实现的方法

<div onclick="doubleclick(this, function(){alert('single')}, function(){alert('double')})">click me</div>

<script>
    var flag = 0;
    function doubleclick(el, onsingle, ondouble) {
        // if (el.getAttribute("data-dblclick") == null) {
            // el.setAttribute("data-dblclick", 1);
        if (flag) {
            flag = 1;
            setTimeout(function () {
                // if (el.getAttribute("data-dblclick") == 1) {
                if (flag) {
                    onsingle();
                }
                // el.removeAttribute("data-dblclick");
                flag = 0;
            }, 300);
        } else {
            // el.removeAttribute("data-dblclick");
            flag = 0;
            ondouble();
        }
    }
</script>

这是一个不错的方法,但是频繁操作dom属性的代码性能较差,不如换成变量

但代码还是存在着缺陷,ie的时间间隔更短

The order of events for a dblclick is:

mousedown
mouseup
click
mousedown
mouseup
click
dblclick
The one exception to this rule is (of course) Internet Explorer with their custom order of:

mousedown
mouseup
click
mouseup
dblclick

通过比较浏览器的事件发生顺序我们可以得到答案

demo

提供一个demo供大家参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值