首先,來了解一下點擊事件發生的先后順序:
單擊:mousedown, mouseup, click
雙擊:mousedown, mouseup, click, mousedown, mouseup, click, dblclick
由於鼠標雙擊時每一次觸發雙擊事件都會引起兩次單擊事件和一次雙擊事件,原生的js不提供專門的雙擊事件。
因為業務原因,雙擊和單機都綁定了不同的業務,在雙擊的時候又觸發了單機,影響了頁面的正常顯示
出現問題的代碼:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script type="text/javascript"> /* * 頁面初始化 */ function onload() { document.addEventListener('click', onDocumentClick); document.addEventListener('dblclick', onDocumenDblClick); } /* * 鼠標單擊事件響應 * event 鼠標事件對象 */ function onDocumentClick(event) { console.log("鼠標單擊"); } /* * 鼠標雙擊事件響應 * event 鼠標事件對象 */ function onDocumenDblClick(event) { console.log("鼠標雙擊"); } </script> </head> <body onload="onload()"> </body> </html>
解決辦法:
setTimerout
所以雙擊時為了屏蔽單擊事件,引入定時器功能,動態的為每次鼠標單擊計時,300ms,300ms內鼠標再次點擊會出發雙擊事件而不走單擊事件
解決代碼:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script type="text/javascript"> //單擊延時觸發 var clickTimeId; /* * 頁面初始化 */ function onload() { document.addEventListener('click', onDocumentClick); document.addEventListener('dblclick', onDocumenDblClick); } /* * 鼠標單擊事件響應 * event 鼠標事件對象 */ function onDocumentClick(event) { // 取消上次延時未執行的方法 clearTimeout(clickTimeId); //執行延時 clickTimeId = setTimeout(function() { //此處為單擊事件要執行的代碼 console.log("鼠標單擊"); }, 250); } /* * 鼠標雙擊事件響應 * event 鼠標事件對象 */ function onDocumenDblClick(event) { // 取消上次延時未執行的方法 clearTimeout(clickTimeId); console.log("鼠標雙擊"); } </script> </head> <body onload="onload()"> </body> </html>
如果還vue 同樣的方法,但是注意有可能會有一些版本不支持,1.0版本是可以,2.0的在線的版本有一些不支持native,到官網中在線引入vue(2019年10月15日)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>測試單擊雙擊</title> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <style> #box{ background-color:pink } </style> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> window.onload=function(){ //var clickTimeId; new Vue({ el:'#box', data:{ clickTimeId:"", }, methods:{ onDocumentClick(event) { // 取消上次延時未執行的方法 clearTimeout(this.clickTimeId); //執行延時 this.clickTimeId = setTimeout(function() { //此處為單擊事件要執行的代碼 console.log("0"); }, 250); }, onDocumenDblClick(event) { // 取消上次延時未執行的方法 clearTimeout(this.clickTimeId); console.log("1"); } } }); }; </script> </head> <body> <button id="box" @click="onDocumentClick" @dblclick="onDocumenDblClick"> 點我啊 </button> </body> </html>
在實際使用過程中還發現了一個有趣的應用,我們知道沒有設置定時器的時候,雙擊的時候是觸發兩次click的事件,如果設置 定時的時間低於170ms的時候 雙擊時會觸發一次單擊的事件 如果有特殊需要也可以控制好定時器的時間
2020年2月15號
在實際組態項目中的時候,因為特殊情況,還是有時間沖突的問題,添加了定時器就導致了頁面的其他業務不能正常使用了,所以最后還是放棄了定時器這種做法
最終的解決辦法:
在單擊的時候記錄下鼠標的xy位置,然后雙擊的結束的時候記錄此時鼠標的xy位置,通過兩次的xy位置進行對比,如果兩次的xy位置相同,或者在一個允許很小的范圍,就證明是雙擊了,其他就當做是單擊處理,這樣一來的問題就都解決,這種方法推薦,親測可試