Javascript / DOM: Как удалить все события объекта DOM? - PullRequest
63 голосов
/ 08 декабря 2010

Просто вопрос: есть ли способ полностью удалить все события объекта, например, Div?

РЕДАКТИРОВАТЬ: я добавляю за div.addEventListener('click',eventReturner(),false); событие.

function eventReturner() {
    return function() {
        dosomething();
    };
}

EDIT2: я нашел способ, который работает, но не возможно использовать для моего случая:

var returnedFunction;
function addit() {
    var div = document.getElementById('div');
    returnedFunction = eventReturner();
    div.addEventListener('click',returnedFunction,false); //You HAVE to take here a var and not the direct call to eventReturner(), because the function address must be the same, and it would change, if the function was called again.
}
function removeit() {
    var div = document.getElementById('div');
    div.removeEventListener('click',returnedFunction,false);
}

Ответы [ 9 ]

79 голосов
/ 08 декабря 2010

Я не уверен, что вы имеете в виду под удалить все события . Удалить все обработчики для определенного типа событий или все обработчики событий для одного типа?

Удалить все обработчики событий

Если вы хотите удалить все обработчики событий (любого типа), вы можете клонировать элемент и заменить его на клон:

var clone = element.cloneNode(true);

Примечание: Это сохранит атрибуты и дочерние элементы, но не сохранит никаких изменений свойств DOM.


Удалить «анонимные» обработчики событий определенного типа

Другой способ - использовать removeEventListener(), но я думаю, вы уже пробовали это, и это не сработало. Вот подвох :

Вызов addEventListener анонимной функции каждый раз создает нового слушателя. Вызов removeEventListener анонимной функции не имеет никакого эффекта . При каждом вызове анонимная функция создает уникальный объект, который не является ссылкой на существующий объект, хотя может вызывать его. При добавлении прослушивателя событий таким образом убедитесь, что он добавлен только один раз, он является постоянным (не может быть удален), пока объект, к которому он был добавлен, не будет уничтожен.

По сути, вы передаете анонимную функцию addEventListener, так как eventReturner возвращает функцию.

Вы должны решить эту проблему:

  1. Не используйте функцию, которая возвращает функцию. Используйте функцию напрямую:

    function handler() {
        dosomething();
    }
    
    div.addEventListener('click',handler,false);
    
  2. Создайте оболочку для addEventListener, в которой хранится ссылка на возвращаемую функцию, и создайте странную функцию removeAllEvents:

    var _eventHandlers = {}; // somewhere global
    
    function addListener(node, event, handler, capture) {
        if(!(node in _eventHandlers)) {
            // _eventHandlers stores references to nodes
            _eventHandlers[node] = {};
        }
        if(!(event in _eventHandlers[node])) {
            // each entry contains another entry for each event type
            _eventHandlers[node][event] = [];
        }
        // capture reference
        _eventHandlers[node][event].push([handler, capture]);
        node.addEventListener(event, handler, capture);
     }
    
    function removeAllListeners(node, event) {
        if(node in _eventHandlers) {
            var handlers = _eventHandlers[node];
            if(event in handlers) {
                var eventHandlers = handlers[event];
                for(var i = eventHandlers.length; i--;) {
                    var handler = eventHandlers[i];
                    node.removeEventListener(event, handler[0], handler[1]);
                }
            }
        }
    }
    

    И тогда вы можете использовать его с:

    addListener(div, 'click', eventReturner(), false)
    // and later
    removeListeners(div, 'click')
    

DEMO

Примечание: Если ваш код выполняется в течение длительного времени, и вы создаете и удаляете много элементов, вам придется обязательно удалять элементы, содержащиеся в _eventHandlers, при их уничтожении.

25 голосов
/ 06 ноября 2016

Используйте собственную функцию прослушивателя событий remove(). Например:

getEventListeners().click.forEach((e)=>{e.remove()})
16 голосов
/ 18 августа 2016

Это удалит всех слушателей из детей, но будет медленным для больших страниц.Жестоко просто написать.

element.outerHTML = element.outerHTML;
9 голосов
/ 26 января 2017

Как говорит corwin.amber, между Webkit и другими существуют различия.

В Chrome:

getEventListeners(document);

Что дает вам Объект со всеми существующими прослушивателями событий:

Object 
 click: Array[1]
 closePopups: Array[1]
 keyup: Array[1]
 mouseout: Array[1]
 mouseover: Array[1]
 ...

Отсюда вы можете связаться со слушателем, которого хотите удалить:

getEventListeners(document).copy[0].remove();

Итак, все слушатели событий:

for(var eventType in getEventListeners(document)) {
   getEventListeners(document)[eventType].forEach(
      function(o) { o.remove(); }
   ) 
}

В Firefox

Немного отличается, потому что использует оболочку слушателя, которая не содержит функции удаления. Вы должны получить слушателя, которого хотите удалить:

document.removeEventListener("copy", getEventListeners(document).copy[0].listener)

Все слушатели события:

for(var eventType in getEventListeners(document)) {
  getEventListeners(document)[eventType].forEach(
    function(o) { document.removeEventListener(eventType, o.listener) }
  ) 
}

Я наткнулся на этот пост, пытаясь отключить надоедливую защиту от копирования новостного сайта.

Наслаждайтесь!

0 голосов
/ 02 июля 2019

Чтобы завершить ответы, приведем реальные примеры удаления событий, когда вы посещаете веб-сайты и не можете контролировать сгенерированный код HTML и JavaScript.

Некоторые раздражающие веб-сайты мешают вам копировать- вставьте имена пользователей в формы входа, которые можно легко обойти, если добавить событие onpaste с атрибутом onpaste="return false" HTML.В этом случае нам просто нужно щелкнуть правой кнопкой мыши поле ввода, выбрать «Проверить элемент» в браузере, таком как Firefox, и удалить атрибут HTML.

Однако, если событие было добавлено через JavaScript, выполните следующие действия:

document.getElementById("lyca_login_mobile_no").onpaste = function(){return false};

Нам придется удалить событие также через JavaScript:

document.getElementById("lyca_login_mobile_no").onpaste = null;

В моем примере я использовал идентификатор "lyca_login_mobile_no", поскольку это был идентификатор ввода текста, используемый веб-сайтом.был в гостях.

Другой способ удалить событие (которое также удалит все события) - это удалить узел и создать новый, как мы должны сделать, если addEventListener использовался для добавления событий с использованиеманонимная функция, которую мы не можем удалить с помощью removeEventListener.Это также можно сделать через консоль браузера, проверив элемент, скопировав код HTML, удалив код HTML, а затем вставив код HTML в то же место.

Это также можно сделать быстрее и автоматизировать с помощью JavaScript:

var oldNode = document.getElementById("lyca_login_mobile_no");
var newNode = oldNode.cloneNode(true);
oldNode.parentNode.insertBefore(newNode, oldNode);
oldNode.parentNode.removeChild(oldNode);

Обновление: если веб-приложение создано с использованием JavaScript-инфраструктуры, такой как Angular, похоже, что предыдущие решения не работают или не нарушают работу приложения.Другим обходным решением, позволяющим вставку, было бы установить значение с помощью JavaScript:

document.getElementById("lyca_login_mobile_no").value = "username";

В настоящее время я не знаю, существует ли способ удалить все события проверки и ограничения формы, не нарушая написанное приложениеполностью в JavaScript, как Angular.

0 голосов
/ 15 января 2019

Только Chrome

Поскольку я пытаюсь удалить EventListener в тесте Protractor и не имею доступа к прослушивателю в тесте, следующее работает для удаления всех прослушивателей событийодного типа:

function(eventType){
    getEventListeners(window).[eventType].forEach(
        function(e){
            window.removeEventListener(eventType, e.listener)
        }
    );
}

Я надеюсь, что это поможет кому-то, так как предыдущий ответ использовал метод «удалить», который с тех пор больше не работает.

0 голосов
/ 21 февраля 2017

Удаление всех событий на document:

Один вкладыш:

for (key in getEventListeners(document)) { getEventListeners(document)[key].forEach(function(c) { c.remove() }) }

Симпатичная версия:

for (key in getEventListeners(document)) {
  getEventListeners(document)[key].forEach(function(c) {
    c.remove()
  })   
}
0 голосов
/ 08 декабря 2010

Может быть, браузер сделает это за вас, если вы сделаете что-то вроде:

Скопируйте div и его атрибуты и вставьте его перед старым, затем переместите содержимое из старого в новое и удалите старое?

0 голосов
/ 08 декабря 2010
var div = getElementsByTagName('div')[0]; /* first div found; you can use getElementById for more specific element */
div.onclick = null; // OR:
div.onclick = function(){};

// edit

Я не знал, какой метод вы используете для прикрепления событий.Для addEventListener вы можете использовать это:

div.removeEventListener('click',functionName,false); // functionName is the name of your callback function

подробнее Подробнее

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...