2017-01-18 237 views
0

我有一個定義事件偵聽器的類方法。讓我們使用下面的代碼片段來簡化。重新綁定JavaScript事件和addEventListener觸發兩次

function bindEvents() { 
 
    document.querySelector('button').addEventListener('click', (e) => { 
 
     console.log('clicked!'); 
 
    }); 
 
} 
 

 
// Initial event binding 
 
bindEvents(); 
 

 
// Rebind events at some point for dynamically created elements 
 
bindEvents();
<button type="button">Click</button>

一切正常使用bindEvents()時只有一次罰款,但例如在執行兩次在聽衆Ajax回調結果再次調用它。所以這意味着在第二個bindEvents()之後,單擊該按鈕將會兩次console.log()等等。有沒有辦法解決這個問題?

我知道我可以在文檔的「動態」結合的活動,並與e.target檢查,但我需要的mouseenter /鼠標離開事件的情況下,我不認爲這是一個好主意,總是有那些事件監聽器該文件。

我讀的地方下面,看來還是假的......

的閱讀進度的方法確保相同的函數引用 不會超過一次相同的元素/事件綁定/捕獲 組合。

我也玩過options參數從這裏https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener,但沒有成功。

對不起,如果這是回答某處,但我沒有找到SO和搜索引擎的答案。

UPDATE:有沒有辦法覆蓋現有的事件監聽器或舊的應該removeEventListenerKCP以下建議被刪除?這個問題有沒有更優雅的解決方案?

回答

1

addEventListener不覆蓋現有的事件偵聽器,它只是簡單地添加一個新的方法名稱暗示。必須使用removeEventListener方法刪除現有的聽衆。

function onClick($event) { 
    console.log('clicked!'); 
} 
function bindEvents() { 
    /** Remove event listener first **/ 
    document.querySelector('button').removeEventListener('click', onClick); 
    document.querySelector('button').addEventListener('click', onClick); 
} 

removeEventListener docs

+0

謝謝你的建議。這肯定會起作用,你認爲這個問題可能有更清晰的解決方案嗎? –

1

除了removeEventListener,您還可以使用事件代表團。通過將事件偵聽器附加到父元素,使用此機制事件是處理程序。

var elem = document.querySelector('div'); 
 

 
elem.addEventListener('click', function(e) { 
 
    e = e || event 
 
    var target = e.target; 
 
    if (target.nodeName != 'BUTTON') 
 
    return; 
 

 
    console.log('clicked ' + target.textContent); 
 
}); 
 

 
//Simulate addition of dynamic elements 
 
setTimeout(function() { 
 
    var newButton = document.createElement('button'); 
 
    newButton.innerHTML = 'Click 2'; 
 
    elem.appendChild(newButton) 
 
}, 2000)
<div> 
 
    <button type="button">Click</button> 
 
</div>

+0

謝謝你的建議。這肯定會起作用。然而,正如我上面寫的那樣,可能會有mousenter/mouseleave事件,我不確定是否讓這些聽衆全天候使用文檔是一個好主意。你怎麼看待這個「問題」? –

+0

@NikolayMihaylov,我們得到的好處是隻附加一個事件處理程序 – Satpal

+0

@NikolayMihaylov並始終附加事件處理程序與靜態父元素 – Satpal

2

的 - 閱讀進度 - 方法確保相同的功能參考將不會超過一次相同的元件結合/事件/捕獲組合。

在你的情況,每次執行bindEvents()因爲你定義一個新功能的完全新的處理程序傳遞給click事件監聽時間(不管它的外觀一樣,它是不同的對象)。每次必須在bindEvents之外定義該處理程序並按名稱(通過引用)傳遞時,要使用相同的處理程序。此作品爲expexted:

function clickHandler(e){ 
 
    alert('clicked!'); 
 
} 
 

 
function bindEvents() { 
 
    document.querySelector('button').addEventListener('click', clickHandler); 
 
} 
 

 
// Initial event binding 
 
bindEvents(); 
 

 
// Rebind events at some point for dynamically created elements 
 
bindEvents();
<button>click</button>

但是與jQuery我用下面的辦法,讓我可以指定只在特定容器中的元素(背景或CTX)將綁定:

$.fn.bindEvents = function bindEvents(ctx){ 
 

 
\t ctx = ctx || this; 
 

 
\t $('button', ctx).on('click', function(event){ 
 
\t \t alert(1); 
 
\t }); 
 
}; 
 

 
$('body').bindEvents(); 
 

 
$('div').bindEvents();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 

 
<button>Click</button> 
 

 
<div><button>in div </button></div>

在上面01的例子會被執行兩次,但第一個按鈕僅被綁定一次,因爲它不在div中。而如果你點擊第二個按鈕,它會提醒兩次,因爲滿足上下文。

+0

謝謝您的建議朋友,將做一些測試,並會回來反饋。 –