2013-10-19 357 views
74

我想刪除使用addEventListener()添加的特定類型的所有事件偵聽器。所有我看到的意思是你的資源,需要這樣做:刪除特定類型的所有事件偵聽器

elem.addEventListener('mousedown',specific_function); 
elem.removeEventListener('mousedown',specific_function); 

但我希望能夠清除它不知道它是什麼目前,像這樣:

elem.addEventListener('mousedown',specific_function); 
elem.removeEventListener('mousedown'); 

回答

150

也就是說不可能不攔截addEventListener調用並跟蹤聽衆或使用允許此類功能的庫不幸。如果可以訪問聽衆集合,但是可以使用feature wasn't implemented

您可以做的最接近的事情是通過克隆該元素來移除所有偵聽器,該元素不會克隆偵聽器集合。

注意:這也將刪除元素的子元素的偵聽器。

var el = document.getElementById('el-id'), 
    elClone = el.cloneNode(true); 

el.parentNode.replaceChild(elClone, el); 
+1

天才,感謝) – Simcha

+1

輝煌,我mustve搜索這100次,這是第一次我看過的東西如此優雅,最好的部分,純js。它不正確使用圖書館的原因,我不得不使用它。再次輝煌! –

+0

我想你假設被替換的節點(帶有事件監聽器)將被垃圾收集。如果情況並非如此,你可能會遇到奇怪的問題。 – Renaud

0

你可以或者覆蓋「yourElement.addEventListener()」方法,並使用了「。適用()方法來執行像正常的聽衆,但在攔截過程中的作用。如:

<script type="text/javascript"> 

    var args = []; 
    var orginalAddEvent = yourElement.addEventListener; 

    yourElement.addEventListener = function() { 
     //console.log(arguments); 
     args[args.length] = arguments[0]; 
     args[args.length] = arguments[1]; 
     orginalAddEvent.apply(this, arguments); 
    }; 

    function removeListeners() { 
     for(var n=0;n<args.length;n+=2) { 
      yourElement.removeEventListener(args[n], args[n+1]); 
     } 
    } 

    removeListeners(); 

</script> 

此腳本必須在頁面加載時運行,否則它可能不會攔截所有事件偵聽器。

確保在使用前刪除'removeListeners()'調用。

-1

一個JS線刪除的元素中的所有聽衆:

element.parentNode.innerHTML += ''; 
+0

如果元素是唯一的孩子,那隻會有副作用。 – plalx

0

我知道這是舊的,但我也有類似的問題,沒有真正的答案,在這裏我想刪除所有「的keydown」事件來自文檔的聽衆。而不是刪除他們,我推翻了的addEventListener忽略他們之前,他們甚至還添加了類似於湯姆斯回答上面,任何其他腳本加載:

<script type="text/javascript"> 
    var current = document.addEventListener; 
    document.addEventListener = function (type, listener) { 
     if(type =="keydown") 
     { 
      //do nothing 
     } 
     else 
     { 
      var args = []; 
      args[0] = type; 
      args[1] = listener; 
      current.apply(this, args); 
     } 
    }; 
</script> 
6

如果之前添加此您通過刪除聽衆唯一目標被停止運行它們,你可以添加一個事件偵聽器窗口捕獲和取消給定類型的所有事件:

window.addEventListener(type, function (event) { 
    event.stopPropagation(); 
}, true); 

true傳遞的第三個參數會導致事件要在路上捕捉下來。停止傳播意味着該事件永遠不會到達收聽它的收聽者。

0

您必須重寫EventTarget.prototype.addEventListener以構建記錄所有'添加偵聽器'調用的陷阱函數。事情是這樣的:

var _listeners = []; 

EventTarget.prototype.addEventListenerBase = EventTarget.prototype.addEventListener; 
EventTarget.prototype.addEventListener = function(type, listener) 
{ 
    _listeners.push({target: this, type: type, listener: listener}); 
    this.addEventListenerBase(type, listener); 
}; 

然後你就可以建立一個EventTarget.prototype.removeEventListener 小號

EventTarget.prototype.removeEventListeners = function(targetType) 
{ 
    for(var index = 0; index != _listeners.length; index++) 
    { 
     var item = _listeners[index]; 

     var target = item.target; 
     var type = item.type; 
     var listener = item.listener; 

     if(target == this && type == targetType) 
     { 
      this.removeEventListener(type, listener); 
     } 
    } 
} 

在ES6你可以使用一個符號,隱藏原有的功能,所有列表直接在實例化對象self中添加偵聽器。

(function() 
{ 
    let target = EventTarget.prototype; 
    let functionName = 'addEventListener'; 
    let func = target[functionName]; 

    let symbolHidden = Symbol('hidden'); 

    function hidden(instance) 
    { 
     if(instance[symbolHidden] === undefined) 
     { 
      let area = {}; 
      instance[symbolHidden] = area; 
      return area; 
     } 

     return instance[symbolHidden]; 
    } 

    function listenersFrom(instance) 
    { 
     let area = hidden(instance); 
     if(!area.listeners) { area.listeners = []; } 
     return area.listeners; 
    } 

    target[functionName] = function(type, listener) 
    { 
     let listeners = listenersFrom(this); 

     listeners.push({ type, listener }); 

     func.apply(this, [type, listener]); 
    }; 

    target['removeEventListeners'] = function(targetType) 
    { 
     let self = this; 

     let listeners = listenersFrom(this); 
     let removed = []; 

     listeners.forEach(item => 
     { 
      let type = item.type; 
      let listener = item.listener; 

      if(type == targetType) 
      { 
       self.removeEventListener(type, listener); 
      } 
     }); 
    }; 
})(); 

您可以測試這個代碼與這個小剪斷:

document.addEventListener("DOMContentLoaded", event => { console.log('event 1'); }); 
document.addEventListener("DOMContentLoaded", event => { console.log('event 2'); }); 
document.addEventListener("click", event => { console.log('click event'); }); 

document.dispatchEvent(new Event('DOMContentLoaded')); 
document.removeEventListeners('DOMContentLoaded'); 
document.dispatchEvent(new Event('DOMContentLoaded')); 
// click event still works, just do a click in the browser