美文网首页大学生世界让前端飞
给一个元素同时绑定click和dbclick存在的问题

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

作者: 缘自世界 | 来源:发表于2017-12-23 18:19 被阅读0次

    这是一个我面试的面试题

    代码实例

    <!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供大家参考

    未经许可不得转载!

    相关文章

      网友评论

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

        本文链接:https://www.haomeiwen.com/subject/rsmqgxtx.html