簡體   English   中英

在 mousedown 和 mouseup 事件之后防止單擊事件

[英]Prevent click event after mousedown & mouseup event

在剛剛觸發 mousedown 和 mouseup 事件之后,jQuery 是否可以防止執行同一元素上的單擊事件。

任何幫助/示例將不勝感激。

有一種尷尬的方法是在鼠標按下時禁用按鈕,並在短時間內啟用它,比如 100 毫秒。 如果 mouseup 在此期間發生,則不會觸發 click。

 $('#btn').on('click', function() { alert('clicked') }); $('#btn').on('mousedown', function() { var btn = $(this); btn.attr('disabled', 'disabled'); setTimeout(function() { btn.removeAttr('disabled'); }, 100); });
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <body> <button id='btn'>Click me</button> </body>

在 Chrome 和 Internet Explorer 中,而不是 Firefox,在 mousedown 或 mouseup 處分離和重新附加元素將阻止觸發單擊事件。 在 Internet Explorer 中,這個技巧不會捕獲雙擊(在 Chrome 中它會)。

但我不會依賴這種奇怪的行為,誰知道它是否會在某個時候改變。 此外,請注意分離和重新附加也會對分離元素的子元素產生副作用(iframe 重新加載,文件字段重置,...)。

有一個解決方案:

 const COORDS = { xDown: null, xUp: null } const handleOnMouseDown = e => { e.preventDefault() COORDS.xUp = null COORDS.xDown = e.clientX } const handleMouseUp = e => { e.preventDefault() COORDS.xUp = e.clientX } const handleOnClick = e => { if (COORDS.xDown !== COORDS.xUp) { e.preventDefault() console.log('drag') } else { console.log('click') } } const el = document.getElementById('test') el.addEventListener('mousedown', handleOnMouseDown) el.addEventListener('mouseup', handleMouseUp) el.addEventListener('click', handleOnClick)
 #test { padding: 20px; display: block; background: #ccc }
 <a href="#" id="test">Link</a>

似乎還沒有人回答過這個問題,至少不是以一種優雅的方式,所以我想我會分享我發現的 NewbeDev 的解決方案(來源: https ://newbedev.com/cancel-click-event-in- 鼠標事件處理程序

答案是使用捕獲階段,因此在您的元素上觸發事件之前,它的所有父級都會在所謂的“捕獲階段”期間收到它。 然后在所謂的“冒泡階段”中,事件被傳遞給您的元素,然后是其父元素。

這里的解決方案是在捕獲階段取消頂部的事件,這樣它就永遠不會在冒泡階段到達您的元素。

我的用例是一個滑塊,所以我使用的代碼是這樣的:

slider.addEventListener('mousedown', ev => {
    // we start sliding (details omitted)

    function captureClick(e) {
        // we cancel the event and stop it from going further.
        // preventDefault() on its own should be enough for most cases
        // Your handler can also check e.defaultPrevented to know if preventDefault() was called
        e.preventDefault();
        // e.stopPropagation();
    }

   window.addEventListener('click', captureClick, true);
   document.addEventListener('mouseup', e => {
       // cleanup - we wait an extra frame to remove our capture 
       //           in case the click event is delayed
       requestAnimationFrame(() => {
           window.removeEventListener('click', captureClick, true);
       });
   });
});

是的,如果你return false; 在 mouseup 處理程序中,因為在 mousedown 和 mouseup 發生后會觸發 onclick。 這在常規 javascript 中是可能的,因此它也應該與 jquery 事件處理程序一起使用。

編輯:

從事件處理程序返回一個布爾值實際上應該足以用於事件消費。 但是,由於這在瀏覽器中非常不穩定,您應該使用該功能來手動取消事件冒泡:

event.stopPropagation();

其中 event 是您的事件處理程序接收的參數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM