在前端开发中, 如果监听了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
可以发现:
click
事件和一次dblclick
事件.click
和dblclick
事件触发几乎在同一时刻, dblclick
事件距第一次click
事件触发时间差144 msclick
事件, 执行了两次并不希望执行的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