Как найти прослушиватели событий на узле DOM при отладке или из кода JavaScript? - PullRequest
762 голосов
/ 15 января 2009

У меня есть страница, на которой некоторые слушатели событий прикреплены к полям ввода и полям выбора. Есть ли способ узнать, какие слушатели событий наблюдают за конкретным узлом DOM и для какого события?

События прикрепляются с использованием:

  1. Прототип Event.observe;
  2. DOM's addEventListener;
  3. как атрибут элемента element.onclick.

Ответы [ 18 ]

490 голосов
/ 06 августа 2010

Если вам просто нужно проверить, что происходит на странице, вы можете попробовать Visual Event bookmarklet.

Обновление : Визуальное событие 2 доступно;

353 голосов
/ 15 января 2009

Зависит от того, как прикреплены события. Для иллюстрации предположим, что у нас есть следующий обработчик кликов:

var handler = function() { alert('clicked!') };

Мы собираемся прикрепить его к нашему элементу, используя разные методы, некоторые из которых разрешают проверку, а некоторые нет.

Метод A) обработчик одного события

element.onclick = handler;
// inspect
alert(element.onclick); // alerts "function() { alert('clicked!') }"

Метод B) несколько обработчиков событий

if(element.addEventListener) { // DOM standard
    element.addEventListener('click', handler, false)
} else if(element.attachEvent) { // IE
    element.attachEvent('onclick', handler)
}
// cannot inspect element to find handlers

Метод C): jQuery

$(element).click(handler);
  • 1.3.x

    // inspect
    var clickEvents = $(element).data("events").click;
    jQuery.each(clickEvents, function(key, value) {
        alert(value) // alerts "function() { alert('clicked!') }"
    })
    
  • 1.4.x (хранит обработчик внутри объекта)

    // inspect
    var clickEvents = $(element).data("events").click;
    jQuery.each(clickEvents, function(key, handlerObj) {
        alert(handlerObj.handler) // alerts "function() { alert('clicked!') }"
        // also available: handlerObj.type, handlerObj.namespace
    })
    

(см. jQuery.fn.data и jQuery.data)

Метод D): Прототип (грязный)

$(element).observe('click', handler);
  • 1.5.x

    // inspect
    Event.observers.each(function(item) {
        if(item[0] == element) {
            alert(item[2]) // alerts "function() { alert('clicked!') }"
        }
    })
    
  • 1.6 - 1.6.0.3 включительно (здесь очень сложно)

    // inspect. "_eventId" is for < 1.6.0.3 while 
    // "_prototypeEventID" was introduced in 1.6.0.3
    var clickEvents = Event.cache[element._eventId || (element._prototypeEventID || [])[0]].click;
    clickEvents.each(function(wrapper){
        alert(wrapper.handler) // alerts "function() { alert('clicked!') }"
    })
    
  • 1.6.1 (немного лучше)

    // inspect
    var clickEvents = element.getStorage().get('prototype_event_registry').get('click');
    clickEvents.each(function(wrapper){
        alert(wrapper.handler) // alerts "function() { alert('clicked!') }"
    })
    
254 голосов
/ 14 мая 2013

Chrome, Firefox, Vivaldi и Safari поддерживают getEventListeners(domElement) в консоли инструментов разработчика.

Для большинства целей отладки это можно использовать.

Ниже очень хорошая ссылка для его использования: https://developers.google.com/chrome-developer-tools/docs/commandline-api#geteventlistenersobject

85 голосов
/ 17 января 2011

WebKit Inspector в браузерах Chrome или Safari теперь делает это. Он отобразит прослушиватели событий для элемента DOM, когда вы выберете его на панели элементов.

67 голосов
/ 22 июня 2011

Можно перечислить всех слушателей событий в JavaScript: это не так сложно; вам просто нужно взломать метод prototype элементов HTML ( до добавления слушателей).

function reportIn(e){
    var a = this.lastListenerInfo[this.lastListenerInfo.length-1];
    console.log(a)
}


HTMLAnchorElement.prototype.realAddEventListener = HTMLAnchorElement.prototype.addEventListener;

HTMLAnchorElement.prototype.addEventListener = function(a,b,c){
    this.realAddEventListener(a,reportIn,c); 
    this.realAddEventListener(a,b,c); 
    if(!this.lastListenerInfo){  this.lastListenerInfo = new Array()};
    this.lastListenerInfo.push({a : a, b : b , c : c});
};

Теперь каждый элемент привязки (a) будет иметь свойство lastListenerInfo, которое содержит всех своих слушателей. И это даже работает для удаления слушателей с анонимными функциями.

45 голосов
/ 19 марта 2014

Использование getEventListeners в Google Chrome :

getEventListeners(document.getElementByID('btnlogin'));
getEventListeners($('#btnlogin'));
41 голосов
/ 22 октября 2012

(переписываем ответ с на этот вопрос , поскольку он уместен здесь.)

При отладке, если вы просто хотите увидеть события, я рекомендую либо ...

  1. Визуальное событие
  2. Раздел Элементы в Инструментах разработчика Chrome: выберите элемент и найдите «Прослушиватели событий» в правом нижнем углу (аналог Firefox)

Если вы хотите использовать события в своем коде и используете jQuery до версии 1.8 , вы можете использовать:

$(selector).data("events")

чтобы получить события. Начиная с версии 1.8, использование .data ("events") больше не поддерживается (см. этот билет об ошибке ). Вы можете использовать:

$._data(element, "events")

Другой пример: записать все события кликов по определенной ссылке в консоли:

var $myLink = $('a.myClass');
console.log($._data($myLink[0], "events").click);

(см. http://jsfiddle.net/HmsQC/ для рабочего примера)

К сожалению, с использованием данных $ ._ это не рекомендуется , за исключением отладки, поскольку это внутренняя структура jQuery, которая может измениться в будущих выпусках. К сожалению, я не знаю других легких способов доступа к событиям.

25 голосов
/ 03 апреля 2014

1: Prototype.observe использует Element.addEventListener (см. исходный код )

2: Вы можете переопределить Element.addEventListener, чтобы запомнить добавленных слушателей (удобное свойство EventListenerList было удалено из предложения спецификации DOM3). Запустите этот код, прежде чем любое событие будет прикреплено:

(function() {
  Element.prototype._addEventListener = Element.prototype.addEventListener;
  Element.prototype.addEventListener = function(a,b,c) {
    this._addEventListener(a,b,c);
    if(!this.eventListenerList) this.eventListenerList = {};
    if(!this.eventListenerList[a]) this.eventListenerList[a] = [];
    this.eventListenerList[a].push(b);
  };
})();

Читать все события по:

var clicks = someElement.eventListenerList.click;
if(clicks) clicks.forEach(function(f) {
  alert("I listen to this function: "+f.toString());
});

И не забудьте переопределить Element.removeEventListener, чтобы удалить событие из пользовательского Element.eventListenerList.

3: свойство Element.onclick нуждается в особом уходе здесь:

if(someElement.onclick)
  alert("I also listen tho this: "+someElement.onclick.toString());

4: не забывайте атрибут содержимого Element.onclick: это две разные вещи:

someElement.onclick = someHandler; // IDL attribute
someElement.setAttribute("onclick","otherHandler(event)"); // content attribute

Так что вам тоже нужно с этим справиться:

var click = someElement.getAttribute("onclick");
if(click) alert("I even listen to this: "+click);

Букмарклет Visual Event (упомянутый в самом популярном ответе) только крадет кэш пользовательского обработчика библиотеки:

Оказывается, что W3C не предоставляет стандартный метод Рекомендуемый интерфейс DOM, чтобы узнать, какие слушатели событий прикреплен к определенному элементу. Хотя это может показаться надзор, было предложение включить свойство под названием eventListenerList к спецификации DOM уровня 3, но был к сожалению был удален в более поздних черновиках. Таким образом, мы вынуждены посмотрел на отдельные библиотеки Javascript, которые обычно поддерживать кэш прикрепленных событий (чтобы их потом можно было удалить и выполнить другие полезные абстракции).

Таким образом, чтобы визуальное событие отображало события, оно должно иметь возможность проанализировать информацию о событии из библиотеки Javascript.

Переопределение элементов может быть сомнительным (т. Е. Потому, что есть некоторые специфические функции DOM, такие как живые коллекции, которые не могут быть закодированы в JS), но он изначально поддерживает eventListenerList и работает в Chrome, Firefox и Opera (не работа в IE7).

21 голосов
/ 06 ноября 2015

Вы можете обернуть нативные методы DOM для управления слушателями событий, поместив это в верхнюю часть вашего <head>:

<script>
    (function(w){
        var originalAdd = w.addEventListener;
        w.addEventListener = function(){
            // add your own stuff here to debug
            return originalAdd.apply(this, arguments);
        };

        var originalRemove = w.removeEventListener;
        w.removeEventListener = function(){
            // add your own stuff here to debug
            return originalRemove.apply(this, arguments);
        };
    })(window);
</script>

H / T @ les2

18 голосов
/ 14 января 2015

Инструменты разработчика Firefox теперь делают это. События отображаются нажатием кнопки «ev» справа от каждого элемента, включая события jQuery и DOM .

Screenshot of Firefox developer tools' event listener button in the inspector tab

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