[javascript] 특정 유형의 모든 이벤트 리스너 제거

를 사용하여 추가 한 특정 유형의 모든 이벤트 리스너를 제거하고 싶습니다 addEventListener(). 내가보고있는 모든 리소스는이 작업을 수행해야한다고 말합니다.

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

그러나 현재와 같은 것을 모르고 정리할 수 있기를 원합니다.

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



답변

addEventListener전화 를 가로 채지 않고 청취자를 추적하거나 그러한 기능을 불행히도 허용하는 라이브러리를 사용 하지 않으면 불가능합니다 . 리스너 콜렉션에 액세스 할 수 있었지만 기능이 구현되지 않은 것 입니다.

가장 가까운 작업은 요소를 복제하여 모든 리스너를 제거하는 것입니다.이 경우 리스너 콜렉션이 복제되지 않습니다.

참고 : 이렇게하면 요소의 자식에서 리스너도 제거됩니다.

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

el.parentNode.replaceChild(elClone, el);


답변

리스너를 제거하여 유일한 목표는 리스너 실행을 중지하는 것입니다. 이벤트 리스너를 창에 추가하여 주어진 유형의 모든 이벤트를 캡처하고 취소 할 수 있습니다.

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

true세 번째 매개 변수를 전달 하면 이벤트가 진행되는 동안 캡처됩니다. 전파를 중지하면 이벤트가 수신 대기중인 청취자에 도달하지 않습니다.


답변

모든 ‘add listener’호출을 로깅하기위한 트랩 함수를 빌드하려면 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에서는 Symbol을 사용하여 인스턴스화 된 객체 자체에서 원래 함수와 추가 된 모든 리스너 목록을 숨길 수 있습니다.

(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


답변

나는 이것이 오래되었다는 것을 알고 있지만 문서에서 모든 “키 다운”이벤트 리스너를 제거하려는 실제 답변이없는 비슷한 문제가있었습니다. 그것들을 제거하는 대신, 다른 스크립트가로드되기 전에 이것을 추가하여 위의 Toms 답변과 유사하게 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>


답변

어떤 콜백이 윈도우 리스너에 연결되어 있는지 알지 못하는 극단적 인 경우, 핸들러는 창 주위를 래퍼 할 수 있으며 addEventListener변수는 removeAllEventListener('scroll')예를 들어 리스너를 저장하여 각 리스너를 올바르게 제거 할 수 있습니다 .

var listeners = {};

var originalEventListener = window.addEventListener;
window.addEventListener = function(type, fn, options) {
    if (!listeners[type])
        listeners[type] = [];

    listeners[type].push(fn);
    return originalEventListener(type, fn, options);
}

var removeAllEventListener = function(type) {
    if (!listeners[type] || !listeners[type].length)
        return;

    for (let i = 0; i < listeners[type].length; i++)
        window.removeEventListener(type, listeners[type][i]);
}


답변

따라서이 함수는 요소에서 지정된 리스너 유형을 대부분 제거합니다.

function removeListenersFromElement(element, listenerType){
  const listeners = getEventListeners(element)[listenerType];
  let l = listeners.length;
  for(let i = l-1; i >=0; i--){
    removeEventListener(listenerType, listeners[i].listener);
  }
 }

어떤 이유로 든 제거 할 수없는 드문 예외가 몇 가지있었습니다.


답변

또는 ‘yourElement.addEventListener ()’메소드를 겹쳐 쓰고 ‘.apply ()’메소드를 사용하여 정상적으로 리스너를 실행하지만 프로세스에서 함수를 인터셉트 할 수 있습니다. 처럼:

<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 ()’호출을 제거하십시오.