JavaScript: ลบตัวฟังเหตุการณ์


142

ฉันกำลังพยายามลบตัวฟังเหตุการณ์ที่อยู่ในนิยามของผู้ฟัง:

canvas.addEventListener('click', function(event) {
    click++;
    if(click == 50) {
        // remove this event listener here!
    }
// More code here ...

ฉันจะทำอย่างนั้นได้อย่างไร? this = event ... ขอบคุณค่ะ


8
เป็นเรื่องเล็กน้อย แต่สำหรับการอ้างอิงในอนาคตif(click == 50) {ควรเป็นif( click === 50 )หรือif( click >= 50 )- พวกเขาจะไม่เปลี่ยนผลลัพธ์ แต่ด้วยเหตุผลด้านสุขภาพการตรวจสอบเหล่านี้มีความหมายมากกว่า
rlemon

คำถามที่ดี ... ฉันจะลบมันได้อย่างไรหากฉันไม่มีสิทธิ์เข้าถึงเนื้อหา ฉันต้องการลบป๊อปอัปสำหรับ onclick บนปุ่มโดยใช้ greasemonkey สำหรับไซต์อื่น ๆ แต่ถ้าฉันไม่สามารถอ้างอิงฟังก์ชันตามชื่อฉันดูเหมือนจะไม่พบวิธีที่จะลบออก
JasonXA

คำตอบ:


125

คุณต้องใช้ฟังก์ชันที่มีชื่อ

นอกจากนี้clickตัวแปรต้องอยู่นอกตัวจัดการเพื่อเพิ่มค่า

var click_count = 0;

function myClick(event) {
    click_count++;
    if(click_count == 50) {
       // to remove
       canvas.removeEventListener('click', myClick);
    }
}

// to add
canvas.addEventListener('click', myClick);

แก้ไข:คุณสามารถปิดรอบ ๆclick_counterตัวแปรดังนี้:

var myClick = (function( click_count ) {
    var handler = function(event) {
        click_count++;
        if(click_count == 50) {
           // to remove
           canvas.removeEventListener('click', handler);
        }
    };
    return handler;
})( 0 );

// to add
canvas.addEventListener('click', myClick);

ด้วยวิธีนี้คุณสามารถเพิ่มตัวนับในองค์ประกอบต่างๆได้


หากคุณไม่ต้องการสิ่งนั้นและต้องการให้แต่ละคนมีตัวนับของตัวเองให้ทำสิ่งนี้:

var myClick = function( click_count ) {
    var handler = function(event) {
        click_count++;
        if(click_count == 50) {
           // to remove
           canvas.removeEventListener('click', handler);
        }
    };
    return handler;
};

// to add
canvas.addEventListener('click', myClick( 0 ));

แก้ไข: ฉันลืมตั้งชื่อตัวจัดการที่ถูกส่งคืนในสองเวอร์ชันล่าสุด แก้ไขแล้ว.


15
+1 - ฉันทำให้มันกลายเป็นซอ แต่มันก็ไม่ได้ผล แต่นั่นเป็นเพราะฉันต้องคลิกห้าสิบครั้ง :) ฉันเป็นคนงี่เง่าจริงๆ ตัวอย่างง่าย ๆ ที่นี่: jsfiddle.net/karim79/aZNqA
karim79

4
@ karim79: ฉันอยากจะบอกว่าฉันไม่เคยทำอะไรแบบนั้นมาก่อน : o) ขอบคุณสำหรับ jsFiddle
user113716

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

Upvote ตัวเลือกที่สามนี่เป็นส่วนสำคัญในการทำความเข้าใจ JS binding / unbinding
SW4

จะmyClick = function(event){...}ถือว่าเป็นฟังก์ชันที่มีชื่อด้วยหรือไม่?
Daniel Möller

82
   canvas.addEventListener('click', function(event) {
      click++;
      if(click == 50) {
          this.removeEventListener('click',arguments.callee,false);
      }

ควรทำ.


15
ที่นี่หนาว! เอกสารarguments.calleeสำหรับบุคคลที่สนใจ: developer.mozilla.org/en/JavaScript/Reference/…
สิ้นสุด

ขอบคุณสิ่งนี้ช่วยได้มาก
John O

2
ขออภัยสิ่งนี้ใช้ไม่ได้กับ ECMAScript 5 (2009) หรือใหม่กว่าจากลิงก์ MDN: "ECMAScript (ES5) รุ่นที่ 5 ห้ามใช้arguments.callee()ในโหมดที่เข้มงวดหลีกเลี่ยงการใช้arguments.callee()โดยตั้งชื่อนิพจน์ฟังก์ชันหรือใช้การประกาศฟังก์ชัน โดยที่ฟังก์ชันต้องเรียกตัวเอง " (แม้ว่าจะใช้callee()แทนcalleeก็ยังคงเอาออก Boo!)
Dai

60

คุณสามารถใช้นิพจน์ฟังก์ชันที่ตั้งชื่อ (ในกรณีนี้คือฟังก์ชันที่ตั้งชื่อabc) เช่น:

let click = 0;
canvas.addEventListener('click', function abc(event) {
    click++;
    if (click >= 50) {
        // remove event listener function `abc`
        canvas.removeEventListener('click', abc);
    }
    // More code here ...
}

ได้อย่างรวดเร็วและตัวอย่างการทำงานสกปรก: http://jsfiddle.net/8qvdmLz5/2/

ข้อมูลเพิ่มเติมเกี่ยวกับการตั้งชื่อการแสดงออกฟังก์ชั่น: http://kangax.github.io/nfe/


ฉลาด. หนึ่งในกรณีที่หายากซึ่งกศน. มีประโยชน์ ขอบคุณ.
DanMan

8
element.querySelector('.addDoor').onEvent('click', function (e) { });
element.querySelector('.addDoor').removeListeners();


HTMLElement.prototype.onEvent = function (eventType, callBack, useCapture) {
this.addEventListener(eventType, callBack, useCapture);
if (!this.myListeners) {
    this.myListeners = [];
};
this.myListeners.push({ eType: eventType, callBack: callBack });
return this;
};


HTMLElement.prototype.removeListeners = function () {
if (this.myListeners) {
    for (var i = 0; i < this.myListeners.length; i++) {
        this.removeEventListener(this.myListeners[i].eType, this.myListeners[i].callBack);
    };
   delete this.myListeners;
};
};

7

หากโซลูชันของ @ Cybernate ไม่ได้ผลให้ลองทำลายทริกเกอร์ในฟังก์ชันของตัวเองเพื่อให้คุณสามารถอ้างอิงได้

clickHandler = function(event){
  if (click++ == 49)
    canvas.removeEventListener('click',clickHandler);
}
canvas.addEventListener('click',clickHandler);

4

หากมีคนใช้ jquery เขาสามารถทำได้ดังนี้:

var click_count = 0;
$( "canvas" ).bind( "click", function( event ) {
    //do whatever you want
    click_count++;
    if ( click_count == 50 ) {
        //remove the event
        $( this ).unbind( event );
    }
});

หวังว่าคงจะช่วยใครได้บ้าง โปรดทราบว่าคำตอบที่ได้รับจาก @ user113716 ใช้ได้ผลดี :)


3

ฉันคิดว่าคุณอาจต้องกำหนดฟังก์ชันตัวจัดการล่วงหน้าดังนี้:

var myHandler = function(event) {
    click++; 
    if(click == 50) { 
        this.removeEventListener('click', myHandler);
    } 
}
canvas.addEventListener('click', myHandler);

วิธีนี้จะช่วยให้คุณสามารถลบตัวจัดการโดยใช้ชื่อจากภายในตัวเอง


-4

ลองนี้มันได้ผลสำหรับฉัน

<button id="btn">Click</button>
<script>
 console.log(btn)
 let f;
 btn.addEventListener('click', f=function(event) {
 console.log('Click')
 console.log(f)
 this.removeEventListener('click',f)
 console.log('Event removed')
})  
</script>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.