programing

JavaScript 또는 디버깅에서 DOM 노드에서 이벤트 청취자를 찾는 방법은 무엇입니까?

randomtip 2022. 12. 31. 18:08
반응형

JavaScript 또는 디버깅에서 DOM 노드에서 이벤트 청취자를 찾는 방법은 무엇입니까?

이벤트 청취자가 입력란과 선택란에 첨부되어 있는 페이지가 있습니다.어떤 이벤트 리스너가 특정 DOM 노드를 감시하고 있는지, 어떤 이벤트를 감시하고 있는지 알 수 있는 방법이 있습니까?

이벤트는 다음 방법으로 첨부됩니다.

  1. Event.observe;
  2. DOM »addEventListener;
  3. 속성 As " " "element.onclick.

Chrome, 및 Chrome, Firefox, Vivaldi safari Safari 원지지getEventListeners(domElement)참の참

디버깅의 대부분은 이 기능을 사용할 수 있습니다.

아래는 사용하기에 매우 좋은 참고 자료입니다.https://developers.google.com/web/tools/chrome-devtools/console/utilities#geteventlisteners

페이지에서 무슨 일이 일어나고 있는지 검사해야 하는 경우 시각적 이벤트 북마크릿을 사용해 보십시오.

업데이트: Visual Event 2 사용 가능.

이벤트가 어떻게 첨부되느냐에 따라 달라집니다.예를 들어 다음과 같은 클릭 핸들러가 있다고 가정합니다.

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

검사 가능한 방법과 그렇지 않은 방법 등 다른 방법을 사용하여 요소에 부착합니다.

방법 A) 단일 이벤트 핸들러

element.onclick = handler;
// inspect
console.log(element.onclick); // "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) {
         console.log(value) // "function() { alert('clicked!') }"
     })
    
  • 1.4.x(핸들러를 오브젝트 안에 저장)

     // inspect
     var clickEvents = $(element).data("events").click;
     jQuery.each(clickEvents, function(key, handlerObj) {
         console.log(handlerObj.handler) // "function() { alert('clicked!') }"
         // also available: handlerObj.type, handlerObj.namespace
     })
    
  • 1.7 이상 (매우 멋짐)

    코멘트의 지식을 살려 만들었습니다.

     events = $._data(this, 'events');
     for (type in events) {
       events[type].forEach(function (event) {
         console.log(event['handler']);
       });
     }
    

(및 을 참조).

방법 D: 프로토타입(메시지)

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

     // inspect
     Event.observers.each(function(item) {
         if(item[0] == element) {
             console.log(item[2]) // "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){
         console.log(wrapper.handler) // "function() { alert('clicked!') }"
     })
    
  • 1.6.1 (약간 개선)

     // inspect
     var clickEvents = element.getStorage().get('prototype_event_registry').get('click');
     clickEvents.each(function(wrapper){
         console.log(wrapper.handler) // "function() { alert('clicked!') }"
     })
    

콘솔에서 결과 출력을 클릭하면(함수의 텍스트를 표시), 콘솔은 관련 JS 파일의 함수 선언 행으로 직접 이동합니다.

이제 Chrome 또는 Safari 브라우저의 WebKit Inspector가 이 작업을 수행합니다.[ Elements ]페인으로 DOM 요소를 선택하면 해당 요소의 이벤트청취자가 표시됩니다.

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위치또한 익명 기능을 가진 청취자를 제거하는 데도 효과가 있습니다.

Google Chrome에서 getEventListeners 사용:

getEventListeners(document.getElementByID('btnlogin'));
getEventListeners($('#btnlogin'));

(이 질문에 대한 답변을 여기에 기재합니다.)

디버깅을 할 때 이벤트만 보고 싶다면 다음 중 하나를 권장합니다.

  1. 비주얼 이벤트
  2. Chrome 개발자 도구의 요소 섹션: 요소를 선택하고 오른쪽 아래에 있는 "이벤트 수신기"를 찾습니다(Firefox에서도 유사).

코드 내의 이벤트를 사용하고 버전 1.8 이전 jQuery를 사용하는 경우 다음을 사용할 수 있습니다.

$(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/ 를 참조해 주세요).

유감스럽게도 $._data를 사용하는 은 내부 jQuery 구조이며 향후 릴리즈에서 변경될 수 있기 때문에 디버깅 외에는 권장되지 않습니다.유감스럽게도 이벤트에 쉽게 접근할 수 있는 다른 방법은 없습니다.

1:Prototype.observeElement.addEventListener 를 사용합니다(소스 코드 참조).

2를 덮어쓸 수 .Element.addEventListenerEventListenerListDOM3 dom dom dom 。이벤트가 연결되기 전에 다음 코드를 실행하십시오.

(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());
});

override이 and and and and and and and and and and and를 덮어쓰는 것도 잊지 마세요.Element.removeEventListener에서 Element.eventListenerList.

: 3: »Element.onclick이치노

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

:Element.onclick: attribute: content attribute: content attribute: content attribute: content attribute attribute attribute

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라는 속성을 레벨3 DOM 사양에 포함시키자는 제안이 있었지만 안타깝게도 이후 초안에서는 삭제되었습니다.따라서 우리는 개별 Javascript 라이브러리를 검토해야 합니다.이 라이브러리는 일반적으로 첨부된 이벤트의 캐시를 유지합니다(따라서 나중에 삭제하고 다른 유용한 추상화를 수행할 수 있습니다).

따라서 Visual Event가 이벤트를 표시하기 위해서는 Javascript 라이브러리에서 이벤트 정보를 해석할 수 있어야 합니다.

요소의 덮어쓰기는 문제가 있을 수 있습니다(즉, 라이브 컬렉션과 같은 일부 DOM 고유의 기능이 있기 때문에 JS에서는 코드화할 수 없습니다). 그러나 eventListenerList는 기본적으로 지원되며 Chrome, Firefox 및 Opera에서는 동작합니다(IE7에서는 동작하지 않습니다.

, 이것을 「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

에 붙여넣기하여 것을 .eventListenersHTML 소 html html html html html

Array.from(document.querySelectorAll("*")).forEach(element => {
    const events = getEventListeners(element)
    if (Object.keys(events).length !== 0) {
         console.log(element, events)
    }
})

이제 Firefox 개발자 도구가 이를 수행합니다.이벤트는 jQuery DOM 이벤트를 포함하여 각 요소의 디스플레이 오른쪽에 있는 "ev" 버튼을 클릭하면 표시됩니다.

인스펙터 탭에 있는 Firefox 개발자 도구의 이벤트 수신기 버튼 스크린샷

Firebug가 있으면console.dir(object or array)JavaScript 스칼라, 어레이 또는 오브젝트의 콘솔로그에 적절한 트리를 인쇄합니다.

시험:

console.dir(clickEvents);

또는

console.dir(window);

Jan Turon의 답변에 기초한 완전한 기능 솔루션 - 다음과 같은 동작getEventListeners()★★★★

(복제된 버그가 있습니다.어쨌든 별로 부러지지 않습니다.)

(function() {
  Element.prototype._addEventListener = Element.prototype.addEventListener;
  Element.prototype.addEventListener = function(a,b,c) {
    if(c==undefined)
      c=false;
    this._addEventListener(a,b,c);
    if(!this.eventListenerList)
      this.eventListenerList = {};
    if(!this.eventListenerList[a])
      this.eventListenerList[a] = [];
    //this.removeEventListener(a,b,c); // TODO - handle duplicates..
    this.eventListenerList[a].push({listener:b,useCapture:c});
  };

  Element.prototype.getEventListeners = function(a){
    if(!this.eventListenerList)
      this.eventListenerList = {};
    if(a==undefined)
      return this.eventListenerList;
    return this.eventListenerList[a];
  };
  Element.prototype.clearEventListeners = function(a){
    if(!this.eventListenerList)
      this.eventListenerList = {};
    if(a==undefined){
      for(var x in (this.getEventListeners())) this.clearEventListeners(x);
        return;
    }
    var el = this.getEventListeners(a);
    if(el==undefined)
      return;
    for(var i = el.length - 1; i >= 0; --i) {
      var ev = el[i];
      this.removeEventListener(a, ev.listener, ev.useCapture);
    }
  };

  Element.prototype._removeEventListener = Element.prototype.removeEventListener;
  Element.prototype.removeEventListener = function(a,b,c) {
    if(c==undefined)
      c=false;
    this._removeEventListener(a,b,c);
      if(!this.eventListenerList)
        this.eventListenerList = {};
      if(!this.eventListenerList[a])
        this.eventListenerList[a] = [];

      // Find the event in the list
      for(var i=0;i<this.eventListenerList[a].length;i++){
          if(this.eventListenerList[a][i].listener==b, this.eventListenerList[a][i].useCapture==c){ // Hmm..
              this.eventListenerList[a].splice(i, 1);
              break;
          }
      }
    if(this.eventListenerList[a].length==0)
      delete this.eventListenerList[a];
  };
})();

사용방법:

someElement.getEventListeners([name])- 리스너의 리턴 , 되어 있는 경우 을 반환한다 " " 、 " " " " " " 。

someElement.clearEventListeners([name])되어 있는 해당 만 삭제됩니다.- 「 」 、 「 」 。

Opera 12(최신 Chrome Webkit 엔진 베이스가 아님) Dragonfly는 한동안 이 기능을 가지고 있었으며 DOM 구조에 분명히 표시되어 있습니다.뛰어난 디버거로 Opera 12 기반 버전을 사용하는 유일한 이유입니다(v13, v14 버전은 없으며 v15 Webkit 기반에는 Dragonfly가 아직 없습니다).

여기에 이미지 설명 입력

프로토타입 1.7.1 방법

function get_element_registry(element) {
    var cache = Event.cache;
    if(element === window) return 0;
    if(typeof element._prototypeUID === 'undefined') {
        element._prototypeUID = Element.Storage.UID++;
    }
    var uid =  element._prototypeUID;           
    if(!cache[uid]) cache[uid] = {element: element};
    return cache[uid];
}

2.과 "jQuery 2.1.$().click() -> $(element).data("events").click;"방식이 작동하지 않습니다.

제 경우 $._data() 함수만 작동한다는 것을 깨달았습니다.

	$(document).ready(function(){

		var node = $('body');
		
        // Bind 3 events to body click
		node.click(function(e) { alert('hello');  })
			.click(function(e) { alert('bye');  })
			.click(fun_1);

        // Inspect the events of body
		var events = $._data(node[0], "events").click;
		var ev1 = events[0].handler // -> function(e) { alert('hello')
		var ev2 = events[1].handler // -> function(e) { alert('bye')
		var ev3 = events[2].handler // -> function fun_1()
        
		$('body')
			.append('<p> Event1 = ' + eval(ev1).toString() + '</p>')
			.append('<p> Event2 = ' + eval(ev2).toString() + '</p>')
			.append('<p> Event3 = ' + eval(ev3).toString() + '</p>');        
	
	});

	function fun_1() {
		var txt = 'text del missatge';	 
		alert(txt);
	}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<body>
</body>

최근에 이벤트 관련 작업을 하고 있었는데 모든 이벤트를 한 페이지에 표시/제어하고 싶었습니다.가능한 해결책을 검토한 후, 나는 나만의 방법으로 이벤트를 감시하는 커스텀 시스템을 만들기로 결정했다.그래서 저는 세 가지를 했습니다.

나는 그 모든 했다: 그 페이지 안에 있는 모든 이벤트 청취자를 위한 용기이다.EventListeners이렇게 세 가지 한 방법이 있습니다.add(),remove() , , , , 입니다.get().

다음에 제가 만든 은 '보다', '보다', '다',EventListener이벤트에 필요한 정보를 보유하는 객체. target,type,callback,options,useCapture,wantsUntrusted했습니다.remove()청취자를 제거합니다.

마지막으로 네이티브를 확장했습니다.addEventListener()그리고.removeEventListener()내가 만든 개체와 함께 작동하도록 하는 방법(EventListener그리고.EventListeners).

사용방법:

var bodyClickEvent = document.body.addEventListener("click", function () {
    console.log("body click");
});

// bodyClickEvent.remove();

addEventListener()작성하다EventListener오브젝트, 추가EventListeners를 반환한다.EventListener나중에 삭제할 수 있습니다.

EventListeners.get()를 사용하여 페이지의 청취자를 표시할 수 있습니다.이 경우,EventTarget또는 문자열(이벤트 유형)을 지정합니다.

// EventListeners.get(document.body);
// EventListeners.get("click");

데모

현재 페이지의 모든 이벤트 청취자를 알고 싶다고 가정해 보겠습니다.그렇게 할 수 있습니다(스크립트 매니저의 확장을 사용하고 있다고 가정하면, 이 경우는 Tampermonkey).다음 스크립트가 이를 수행합니다.

// ==UserScript==
// @name         New Userscript
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @include      https://stackoverflow.com/*
// @grant        none
// ==/UserScript==

(function() {
    fetch("https://raw.githubusercontent.com/akinuri/js-lib/master/EventListener.js")
        .then(function (response) {
            return response.text();
        })
        .then(function (text) {
            eval(text);
            window.EventListeners = EventListeners;
        });
})(window);

그리고 청취자 명단을 보니까 299명이라고 나오네요."복제된 것"이 있을 것 같은데, 정말 중복된 것인지는 모르겠어요.모든 이벤트 유형이 중복되는 것은 아니기 때문에 이러한 "복제"는 개별 리스너일 수 있습니다.

이 페이지의 모든 이벤트청취자를 나열하는 콘솔 스크린샷

코드는 내 저장소에서 찾을 수 있습니다.좀 길어서 여기에 올리기 싫었어요.


업데이트: jQuery에서는 작동하지 않는 것 같습니다.EventListener를 조사하면 콜백이

function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}

이것은 jQuery의 것으로 실제 콜백은 아니라고 생각합니다.jQuery는 실제 콜백을 EventTarget 속성에 저장합니다.

$(document.body).click(function () {
    console.log("jquery click");
});

여기에 이미지 설명 입력

이벤트 리스너를 삭제하려면 실제 콜백을removeEventListener()법법. 필요합니다.jQuery 에에ququququququququququququququququququ.★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

nice jQuery Events 확장자가 있습니다.

여기에 이미지 설명 입력 (출처 표시)

다음 기능을 변경하면 추가된 청취자를 기록할 수 있습니다.

EventTarget.prototype.addEventListener
EventTarget.prototype.attachEvent
EventTarget.prototype.removeEventListener
EventTarget.prototype.detachEvent

나머지 청취자의 마음을 읽다

console.log(someElement.onclick);
console.log(someElement.getAttribute("onclick"));

언급URL : https://stackoverflow.com/questions/446892/how-to-find-event-listeners-on-a-dom-node-in-javascript-or-in-debugging

반응형