จะค้นหาตัวฟังเหตุการณ์บนโหนด DOM ได้อย่างไรเมื่อทำการดีบั๊กหรือจากรหัส JavaScript


840

ฉันมีหน้าเว็บที่มีผู้ฟังเหตุการณ์บางรายติดอยู่กับกล่องป้อนข้อมูลและกล่องที่เลือก มีวิธีการค้นหาว่าผู้ฟังเหตุการณ์ใดกำลังสังเกตโหนด DOM เฉพาะและสำหรับเหตุการณ์ใด

กิจกรรมที่แนบมาโดยใช้:

  1. ต้นแบบของ Event.observe ;
  2. DOM ของ addEventListener ;
  3. element.onclickในฐานะที่เป็นแอตทริบิวต์ขององค์ประกอบ

3
เหตุการณ์ที่แนบมาในครั้งแรกเป็นอย่างไร คุณใช้ห้องสมุด (เช่น Prototype, jQuery เป็นต้น)?
Crescent Fresh

เป็นสิ่งสำคัญที่จะต้องทราบว่าสามารถเชื่อมต่อฟังก์ชันการโทรกลับหลายรายการสำหรับเหตุการณ์ประเภทเดียวกันได้element.addEventListener(type, callback, [bubble])ในขณะที่element.onclick = functionจะเขียนทับทุกครั้งที่คุณกำหนด
Braden ที่ดีที่สุด

คำตอบ:


507

หากคุณเพียงแค่ต้องตรวจสอบสิ่งที่เกิดขึ้นบนหน้าคุณอาจลองbookmarklet เหตุการณ์ภาพ

ปรับปรุง : ภาพเหตุการณ์ 2ใช้ได้


1
ที่สมบูรณ์แบบ! EventBugปลั๊กอินของ Beats Firebug
Robin Maben

22
นี่เป็นการเพิ่มองค์ประกอบ jillion ให้กับหน้าซึ่งส่วนมากเป็นรูปภาพ มีประโยชน์ลดลงอย่างมากในหน้าเว็บที่มีตัวจัดการเหตุการณ์จำนวนมาก (ของฉันมี 17k และเหตุการณ์ที่มองเห็นใช้เวลาในการโหลดประมาณ 3 นาที)
Tony R

15
ฉันเชื่อว่าส่วนขยายของ Chrome @ssharma ที่กล่าวถึงนั้นมีอยู่ที่นี่
kmote

1
Visial Event ไม่ทำงานหากเพจอ้างถึงไลบรารี js ของบุคคลที่สาม มันยกข้อผิดพลาด: XMLHttpRequest ไม่สามารถโหลดA.com/js/jquery-ui-1.10.3.custom.js?_=1384831682813 Origin B.comไม่ได้รับอนุญาตจาก Access-Control-Allow-Origin
hiway

5
เครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ Chrome และ FF ภายใน (F12) มีตัวแสดงเหตุการณ์ในตัว! Chrome: บนแท็บ "องค์ประกอบ" ให้เลือกและองค์ประกอบและดูทางด้านขวามีดังนี้: สไตล์, คำนวณ, ฟังเหตุการณ์
oriadam

365

ขึ้นอยู่กับว่ามีการแนบกิจกรรมอย่างไร สำหรับภาพประกอบสมมติเรามีตัวจัดการคลิกดังต่อไปนี้:

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!') }"
    })

3
ขอบคุณสำหรับการอัปเดตนี้ โชคร้ายที่คุณต้องทำซ้ำผ่านตัวจัดการแต่ละประเภท
Keith Bentrup

4
ใน "วิธีการ B" (addEventListener) นี่คือคำตอบเกี่ยวกับสถานะของสิ่งอำนวยความสะดวกการแจงนับสำหรับตัวจัดการที่ลงทะเบียนกับ DOM เหตุการณ์ API บริสุทธิ์: stackoverflow.com/questions/7810534/…
Nickolay

@ John: ขอบคุณสำหรับความคิดเห็น คุณมีตัวอย่างของ "JavaScript จริง" เพื่อดึงผู้ฟังที่เพิ่มเข้าไปก่อนหน้านี้ผ่านทางaddEventListener?
Crescent Fresh

6
@Jan ดูเหมือนว่านี่จะใช้งานไม่ได้กับ jQuery 1.7.2 มีแนวทางอื่นสำหรับรุ่นนั้นหรือไม่
tomdemuyt

14
@tomdemuyt ใน jQuery ตอนนี้เหตุการณ์จะถูกเก็บไว้ในอาร์เรย์ข้อมูลภายในแทนที่จะสามารถเข้าถึงได้.data('events')เหมือนอย่างที่เคยเป็นมาก่อน $._data(elem, 'events')ในการเข้าถึงข้อมูลเหตุการณ์ภายในการใช้งาน โปรดทราบว่าฟังก์ชั่นนี้มีการทำเครื่องหมาย "สำหรับใช้ภายในเท่านั้น" ในแหล่ง jQuery ดังนั้นจึงไม่มีคำสัญญาว่ามันจะทำงานได้ในอนาคต แต่ฉันเชื่อว่ามันใช้งานได้ตั้งแต่ jQuery 1.7 และยังใช้งานได้
Matt Browne

350

การสนับสนุน Chrome, Firefox, Vivaldi และ Safari getEventListeners(domElement)ในคอนโซลเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์

สำหรับวัตถุประสงค์ในการดีบักส่วนใหญ่สามารถใช้สิ่งนี้ได้

ด้านล่างนี้เป็นข้อมูลอ้างอิงที่ดีมากที่จะใช้: https://developers.google.com/web/tools/chrome-devtools/console/utilities#geteventlisteners


1
+1 รหัสเฉพาะเบราว์เซอร์ไม่ใช่ปัญหาสำหรับฉันเพราะฉันกำลังพยายามหาเพจที่ฉันไม่สามารถควบคุมการทำงานได้อย่างถูกต้อง
Grault

9
ดี แต่ใช้งานได้ในบรรทัดคำสั่งของคอนโซล Chrome :(
gillyspy

5
@Raghav อาขอบคุณการใช้งานไม่ใช่:อย่างที่ฉันคิดครั้งแรก :)getEventListeners(object) obj getEventListeners()
jave.web

11
คุณสามารถช่วยฉันได้ 3 ชั่วโมงถ้าคุณได้อธิบายวิธีรับซอร์สโค้ดของ Eventlistener "การอ้างอิง" นั้นไม่ได้อธิบายอะไรเลย var list = getEventListeners(document.getElementById("YOURIDHERE")); console.log(list["focus"][0]["listener"].toString())ในกรณีที่คนอื่นอยู่บนความสูญเสียที่นี่มีวิธีการดังนี้ เปลี่ยน "โฟกัส" เป็นเหตุการณ์ที่คุณต้องการตรวจสอบและจำนวนหากมีผู้ฟังหลายคนในเหตุการณ์เดียวกัน
doABarrelRoll721

46
เคล็ดลับ: getEventListeners($0)จะรับฟังเหตุการณ์สำหรับองค์ประกอบที่คุณมุ่งเน้นในเครื่องมือ Chrome dev ฉันใช้สิ่งนี้ตลอดเวลา ความรักไม่ต้องใช้ querySelector หรือ get__By_ ฟังก์ชั่น
cacoder

91

ตัวตรวจสอบ WebKit ใน Chrome หรือเบราว์เซอร์ Safari จะทำเช่นนี้ มันจะแสดงฟังเหตุการณ์สำหรับองค์ประกอบ DOM เมื่อคุณเลือกในบานหน้าต่างองค์ประกอบ


9
ฉันไม่แน่ใจว่าจะแสดงตัวจัดการเหตุการณ์ทั้งหมดหรือไม่ เพียงแค่จัดการเหตุการณ์ HTML เดียว
huyz

3
ฉันควรพูดถึงปลั๊กอิน EventBug สำหรับ Firebug เพื่อความสมบูรณ์ < softwareishard.com/blog/category/eventbug >
Nickolay

นี่เพิ่งทำให้วันของฉันรหัสต้นแบบดั้งเดิมมีฟังก์ชั่นหลายอย่างที่เชื่อมโยงกับเหตุการณ์เดียวกันในองค์ประกอบเดียวกันและฉันกำลังจะตายที่พยายามติดตามพวกเขา ขอบคุณมาก Ishan
siliconrockstar

70

เป็นไปได้ที่จะแสดงรายการผู้ฟังเหตุการณ์ทั้งหมดใน 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คุณสมบัติที่มีผู้ฟังทั้งหมด และยังใช้งานได้กับการลบฟังด้วยฟังก์ชั่นนิรนาม


4
วิธีนี้จะไม่ทำงานหากคุณกำลังเขียนสคริปต์ผู้ใช้หรือสคริปต์เนื้อหา ไม่เพียง แต่มีแนวโน้มว่าจะถูก sandboxed ในวันนี้ แต่คุณจะรับประกันการสั่งการได้อย่างไร?
huyz

วิธีนี้ใช้ได้กับ chrome / 19 และ FF / 12 คำสั่งของการดำเนินการสามารถรับประกันได้ถ้าคุณขอสิ่งนี้ก่อนสคริปต์อื่น ๆ
Tzury Bar Yochay

8
คุณไม่สามารถปรับเปลี่ยนNode.prototypeแทนได้ใช่ไหม นั่นคือสิ่งที่HTMLAnchorElementสืบทอด.addEventListenerมาจากไหน '
Esailija

3
คุณกำลังสมมติว่าตัวแทนผู้ใช้ใช้การสืบทอดต้นแบบสำหรับวัตถุโฮสต์ DOM และอนุญาตให้คุณแก้ไข ทั้งผู้ที่มีความคิดที่ดี: ไม่ได้ปรับเปลี่ยนวัตถุที่คุณทำไม่ได้เอง
RobG

1
นี่เป็นสิ่งที่ไร้ประโยชน์ - มันแสดงให้เห็นว่ามีการเพิ่มตัวเพิ่มเหตุการณ์อะไรซึ่งอาจทำได้ดีในบางกรณี แต่ไม่ใช่สิ่งที่ถูกลบออกไป ดังนั้นหากคุณพยายามที่จะแก้ไขข้อผิดพลาดสิ่งที่ถูกลบไปและสิ่งที่ไม่ได้เกิดขึ้นก็ไม่มีทาง
gotofritz

52

ใช้ getEventListeners ในGoogle Chrome :

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

1
Uncaught ReferenceError: getEventListeners ไม่ได้ถูกกำหนด
Bryan Grace

3
getEventListeners ใช้งานได้เฉพาะในคอนโซล devtools ของ Chrome และนี่คือคำตอบที่ซ้ำซ้อนนี้มากขึ้น: stackoverflow.com/a/16544813/1026
Nickolay

41

(เขียนซ้ำคำตอบจากคำถามนี้เนื่องจากเกี่ยวข้องกับที่นี่)

เมื่อทำการดีบั๊กหากคุณต้องการดูเหตุการณ์ฉันขอแนะนำ ...

  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 ภายในและสามารถเปลี่ยนแปลงได้ในการเผยแพร่ในอนาคต น่าเสียดายที่ฉันรู้ว่าไม่มีวิธีง่าย ๆ ในการเข้าถึงเหตุการณ์


1
$._data(elem, "events")ไม่ปรากฏในการทำงานกับ jQuery 1.10 $(elem).on('event', ...)อย่างน้อยสำหรับเหตุการณ์ที่เกิดขึ้นโดยใช้ที่ลงทะเบียน ไม่มีใครรู้วิธีแก้จุดบกพร่องเหล่านั้นหรือไม่
Marius Gedminas

4
ฉันไม่ได้เป็นบวก แต่ฉันคิดว่าพารามิเตอร์แรก$._dataอาจต้องเป็นองค์ประกอบและไม่ใช่วัตถุ jQuery ดังนั้นฉันต้องแก้ไขตัวอย่างข้างต้นให้เป็นconsole.log($._data($myLink[0], "events").click);
ลุค

29

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

bookmarklet Visual Visual (กล่าวถึงในคำตอบที่ได้รับความนิยมมากที่สุด) จะขโมยแคชตัวจัดการไลบรารีที่กำหนดเองเท่านั้น:

ปรากฎว่าไม่มีวิธีมาตรฐานให้โดยอินเทอร์เฟซ DOM แนะนำ W3C เพื่อค้นหาสิ่งที่แนบมาฟังองค์ประกอบเหตุการณ์ แม้ว่าสิ่งนี้อาจดูเหมือนเป็นการกำกับดูแล แต่ก็มีข้อเสนอที่จะรวมคุณสมบัติที่เรียกว่า eventListenerList ไปยังข้อมูลจำเพาะ DOM ระดับ 3 แต่โชคไม่ดีที่ถูกลบออกในร่างภายหลัง ด้วยเหตุนี้เราจึงถูกบังคับให้ดูที่ห้องสมุด Javascript แต่ละแห่งซึ่งโดยทั่วไปจะรักษาแคชของเหตุการณ์ที่แนบมา (เพื่อให้สามารถลบออกได้ในภายหลังและดำเนินการกับบทคัดย่อที่เป็นประโยชน์อื่น ๆ )

ด้วยเหตุนี้เพื่อให้ Visual Event สามารถแสดงกิจกรรมได้จึงต้องสามารถแยกข้อมูลกิจกรรมออกจากไลบรารี Javascript ได้

การแทนที่องค์ประกอบอาจเป็นปัญหา (เช่นเนื่องจากมีคุณสมบัติบางอย่างของ DOM เช่นคอลเลกชันสดซึ่งไม่สามารถเข้ารหัสใน JS ได้) แต่ให้การสนับสนุน eventListenerList ในลักษณะดั้งเดิมและทำงานได้ใน Chrome, Firefox และ Opera (ไม่ทำงานใน IE7 )


23

คุณสามารถสรุปวิธี 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


โปรดแก้ไขให้ฉันด้วยหากฉันผิด แต่ไม่ใช่สำหรับผู้ฟังเหตุการณ์ที่แนบมากับหน้าต่างเท่านั้น
Maciej Krawczyk

@MaciejKrawczyk yep และฟองนั้น
Jon z

18

ตอนนี้เครื่องมือสำหรับนักพัฒนา Firefox ทำเช่นนี้ เหตุการณ์จะแสดงโดยคลิกที่ปุ่ม "EV" ที่ด้านขวาของจอแสดงผลแต่ละองค์ประกอบรวมทั้งjQueryและDOMเหตุการณ์

สกรีนช็อตของปุ่มเครื่องมือฟังเหตุการณ์นักพัฒนา Firefox ในแท็บตัวตรวจสอบ


ฉันได้ดูองค์ประกอบ dom อย่างใดอย่างหนึ่งบนหน้าเว็บที่คั่นหน้าเหตุการณ์ Visual Visual 2 แสดงเหตุการณ์แบบมีสายและฉันเห็นปุ่ม "ev" เล็ก ๆ ทางด้านขวาเหมือนที่คุณแสดง
Eric

ผู้ฟังเหตุการณ์ของ Firefox สามารถค้นหากิจกรรมที่ได้รับมอบหมาย jQuery ในขณะที่ Chrome ต้องการปลั๊กอินเพื่อทำมัน
Nick Tsai

12

หากคุณมีFirebugคุณสามารถใช้console.dir(object or array)พิมพ์ต้นไม้ที่ดีในบันทึกของคอนโซลสเกลา JavaScript อาร์เรย์หรือวัตถุใด ๆ

ลอง:

console.dir(clickEvents);

หรือ

console.dir(window);

9
ฟีเจอร์ใหม่ใน firebug 1.12 getfirebug.com/wiki/index.php/GetEventListeners
Javier Constanzo

10

วิธีการแก้ปัญหาการทำงานอย่างเต็มที่ตามคำตอบโดย 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]) - ลบผู้ฟังเหตุการณ์ทั้งหมดหากตั้งชื่อไว้จะลบผู้ฟังเหตุการณ์เท่านั้น


3
นี่เป็นคำตอบที่ดี แต่ฉันไม่สามารถใช้มันกับองค์ประกอบbodyและ document
David Bradshaw

ทางออกที่ดีจริงๆ!
Dzhakhar Ukhaev

@Peter Mortensen ทำไมคุณถึงเปลี่ยนชื่อ Jan :)
n00b

1
@ David Bradshaw: เพราะร่างกายเอกสารและหน้าต่างมีต้นแบบของตัวเองและไม่ได้ต้นแบบธาตุ ...
สเตฟาน Steiger

1
@ n00b: มีข้อบกพร่อง นั่นเป็นเหตุผลที่อืม คุณใช้เครื่องหมายจุลภาคในคำสั่ง if สำหรับ listener และ useCaption ... ตัวดำเนินการเครื่องหมายจุลภาคประเมินแต่ละตัวถูกดำเนินการ (จากซ้ายไปขวา) และส่งกลับค่าของตัวถูกดำเนินการสุดท้าย ดังนั้นคุณจึงลบ eventListener แรกที่ตรงกับ useCapture โดยไม่คำนึงถึงประเภทของเหตุการณ์ ... นั่นควร && แทนที่จะเป็นเครื่องหมายจุลภาค
Stefan Steiger

8

Opera 12 (ไม่ใช่เครื่องมือ Chrome Webkit ล่าสุด) Dragonflyได้ใช้งานมาระยะหนึ่งและแสดงให้เห็นอย่างชัดเจนในโครงสร้าง DOM ในความคิดของฉันมันเป็น debugger ที่เหนือกว่าและเป็นเหตุผลเดียวที่เหลืออยู่ทำไมฉันยังคงใช้ Opera 12 เวอร์ชันตาม (ไม่มี v13, v14 รุ่นและ v15 Webkit ตามขาด Dragonfly ยัง)

ป้อนคำอธิบายรูปภาพที่นี่


4

ต้นแบบ 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];
}

4

ฉันเพิ่งทำงานกับกิจกรรมและต้องการดู / ควบคุมกิจกรรมทั้งหมดในหน้า เมื่อพิจารณาถึงวิธีการแก้ปัญหาที่เป็นไปได้ฉันตัดสินใจที่จะไปตามทางของตัวเองและสร้างระบบที่กำหนดเองเพื่อติดตามเหตุการณ์ ดังนั้นฉันทำสามสิ่ง

ก่อนอื่นฉันต้องการคอนเทนเนอร์สำหรับผู้ฟังเหตุการณ์ทั้งหมดในหน้านั่นคือ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");
});

ป้อนคำอธิบายรูปภาพที่นี่

ในการลบ listener เหตุการณ์จำเป็นต้องส่งการเรียกกลับที่แท้จริงไปยังremoveEventListener()เมธอด ดังนั้นเพื่อให้การทำงานกับ jQuery นี้ต้องการการแก้ไขเพิ่มเติม ฉันอาจแก้ไขได้ในอนาคต


ใช้งานได้ดี! ขอบคุณ
mt025

3

ฉันพยายามทำเช่นนั้นใน 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>



1

การเปลี่ยนฟังก์ชั่นเหล่านี้จะช่วยให้คุณบันทึกผู้ฟังที่เพิ่มเข้ามา:

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

อ่านส่วนที่เหลือของผู้ฟังด้วย

console.log(someElement.onclick);
console.log(someElement.getAttribute("onclick"));
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.