JavaScript中click与dblclick冲突与共存


在前端开发中, 如果监听了DOM元素的click事件, 且监听了dblclick事件, 会导致某 些冲突.

冲突

如实现以下功能

  • 单击input按钮, 设置box元素颜色为绿色.
  • 双击input按钮, 设置box元素颜色为红色.

以下是示例代码:

<!DOCTYPE html>
<html>
<head>
    <title>click and dblclick test</title>
    <meta charset="utf-8" />
</head>
<body>
    <h1>click and dblclick test</h1>
    <div><input type="button" value="double click here"></div>
    <div id="box">color will be changed</div>
    <script>
        var input = document.querySelector('input'),
            box = document.querySelector('#box'),
            /**
             * @param {String} color
             */
            setBoxColor = function (color) {
                console.log('setBoxColor: ' + color);
                box.style.color = color;
            };
        input.addEventListener('click', function () {
            console.log('click ' + (new Date()).getTime());
            setBoxColor('green');
        }, false);

        input.addEventListener('dblclick', function () {
            console.log('dblclick ' + (new Date()).getTime());
            setBoxColor('red');
        }, false);
    </script>
</body>
</html>

在Chrome上运行以上代码并双击input按钮, console会显示类似如下的结果:

click 1390545338752             click-and-dblclick-js-test.html:22
setBoxColor: green              click-and-dblclick-js-test.html:18
click 1390545338895             click-and-dblclick-js-test.html:22
setBoxColor: green              click-and-dblclick-js-test.html:18
dblclick 1390545338896          click-and-dblclick-js-test.html:27
setBoxColor: red                click-and-dblclick-js-test.html:18

可以发现:

  1. 一次双击操作, 触发了两次click事件和一次dblclick事件.
  2. 第二次clickdblclick事件触发几乎在同一时刻, dblclick事件距第一次click事件触发时间差144 ms
  3. 在双击操作中, 连续触发的两次click事件, 执行了两次并不希望执行click事件监听器.

解决

导致双击操作中, 连续执行两次并不希望执行click事件监听器的根本原因是:

  • 双击操作依赖两次单击操作

没有办法改变浏览器触发单/双击事件的机制, 但有办法避免在双击过程中执行两次并不 希望执行click事件监听器吗?

以下是解决办法:

<!DOCTYPE html>
<html>
<head>
    <title>click and dblclick fix</title>
    <meta charset="utf-8" />
</head>
<body>
    <h1>click and dblclick fix</h1>
    <div><input type="button" value="double click here"></div>
    <div id="box">color will be changed</div>
    <script>
        var input = document.querySelector('input'),
            box = document.querySelector('#box'),
            /**
             * @param {String} color
             */
            setBoxColor = function (color) {
                console.log('setBoxColor: ' + color);
                box.style.color = color;
            },
            clickTimeout = {
                _timeout: null,
                /**
                 *
                 */
                set: function (fn) {
                    var that = this;
                    that.clear();
                    that._timeout = window.setTimeout(fn, 300);
                },
                clear: function () {
                    var that = this;
                    if (that._timeout) {
                        window.clearTimeout(that._timeout);
                    }
                }
            };
        input.addEventListener('click', function () {
            console.log('click ' + (new Date()).getTime());
            clickTimeout.set(function () {
                setBoxColor('green');
            });
        }, false);

        input.addEventListener('dblclick', function () {
            clickTimeout.clear();
            console.log('dblclick ' + (new Date()).getTime());
            setBoxColor('red');
        }, false);
    </script>
</body>
</html>


运行并双击input按钮:

click 1390547289426         click-and-dblclick-js-fix.html:39
click 1390547289552         click-and-dblclick-js-fix.html:39
dblclick 1390547289553      click-and-dblclick-js-fix.html:47
setBoxColor: red            click-and-dblclick-js-fix.html:18

在双击过程中, click事件监听器依然会被连续执行两次, 但setBoxColor函数不会被 click事件监听器调用了.

缺点

以上解决方案的缺点是:

  • 单击操作下的setBoxColor的执行开始时间比正常情况要慢300 ms
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值