雙擊事件(dblclick)時,不觸發單擊事件(click)

殺了我吧發表於2019-02-16

事件繫結中,執行雙擊事件(dblclick)時能觸發兩次單擊事件(click)。即一個標籤元素(如button等),如果元素同時繫結了單擊事件(click)和雙擊事件(dblclick),那麼執行單擊事件(click)時,不會觸發雙擊事件(dblclick), 執行雙擊事件(dblclick)時卻會觸發兩次單擊事件(click)。

先看一下點選事件的執行順序:

單擊(click):mousedown,mouseout,click;
雙擊(dblclick):mousedown,mouseout,click , mousedown,mouseout,click,dblclick;

在單擊的時候不會執行雙擊,但是雙擊的時候會執行兩次單擊再執行雙擊事件。
解決的思路:使用定時器清除掉兩個單擊事件,留下一個雙擊事件。

setTimeout

<button onclick="single(event)" ondblclick="double(event)">按鈕</button>

var time = 200;
var timeOut  = null;

function single (e) {
    clearTimeout(timeOut); // 清除第一個單擊事件
    timeOut= setTimeout(function () {
        console.log(`單擊`);
        // 單擊事件的程式碼執行區域
        // ...
    }, time)
}
function double (e) {
    clearTimeout(timeOut); // 清除第二個單擊事件
    console.log(`雙擊`)
    // 雙擊的程式碼執行區域
    // ...
}

然後現在,單擊按鈕列印“單擊”,雙擊按鈕列印“雙擊”。

關於 time=200,大家知道js的事件迴圈機制,點選事件會新增一個任務佇列。time=0, 也會新增一個任務佇列。那麼time=0與time=200有什麼區別呢?

因為第一次單擊事件後,主執行緒沒有任何任務,就會立馬執行這個單擊事件的任務。待第二次單擊的時候,假設距離第一次單擊事件是150ms, 如果你的定時器小於150ms, 那麼第一次的任務佇列就會執行完。
要想不執行第一次的任務佇列,那麼定時器時間間隔就必須大於兩次單擊的時間間隔了。所以,這個200是酌情值,大於間隔就行。

第一次單擊任務不執行了,是被定時器延時,然後第二次點選的時候給清除了。那麼第二次點選事件呢?
在兩次單擊之後,會立馬執行一個雙擊事件,雙擊事件的一開頭就把這個第二次點選事件給清除了。

這就是雙擊事件的大概過程。

相關文章