JavaScript: xóa trình nghe sự kiện


136

Tôi đang cố gắng loại bỏ một người nghe sự kiện bên trong một định nghĩa người nghe:

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

Làm thế nào tôi có thể làm điều đó? đây = sự kiện ... Cảm ơn bạn.


8
tầm thường nhưng đối với các tài liệu tham khảo trong tương lai if(click == 50) {nên if( click === 50 )hoặc if( click >= 50 )- chúng sẽ không thay đổi đầu ra, nhưng vì lý do rõ ràng, các kiểm tra này có ý nghĩa hơn.
rlemon

Câu hỏi hay ... làm cách nào để xóa nó nếu tôi không có quyền truy cập vào nội dung? Tôi muốn xóa cửa sổ bật lên để bật onclick trên các nút bằng greasemonkey cho các trang web khác, nhưng trừ khi tôi có thể tham chiếu chức năng theo tên, tôi dường như không tìm cách xóa nó.
JasonXA

Câu trả lời:


121

Bạn cần sử dụng các chức năng được đặt tên.

Ngoài ra, clickbiến cần phải nằm ngoài bộ xử lý để tăng.

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

EDIT: Bạn có thể đóng xung quanh click_counterbiến như thế này:

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

Bằng cách này, bạn có thể tăng bộ đếm trên một số yếu tố.


Nếu bạn không muốn điều đó và muốn mỗi người có một quầy riêng, thì hãy làm điều này:

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

EDIT: Tôi đã quên đặt tên cho trình xử lý được trả lại trong hai phiên bản trước. Đã sửa.


14
+1 - Tôi đã biến điều này thành một trò đùa và nó không hoạt động. Nhưng đó là vì tôi cần phải bấm năm mươi lần :) Thật là một thằng ngốc. Ví dụ đơn giản tại đây: jsfiddle.net/karim79/aZNqA
karim79

4
@ karim79: Tôi ước tôi có thể nói rằng tôi chưa bao giờ làm điều gì như vậy trước đây. : o) Cảm ơn vì jsFiddle.
dùng113716

+1 Tùy chọn thứ ba làm việc cho tôi. Chỉ định một sự kiện quan trọng cho một trường đầu vào để xóa xác nhận. Xin chân thành cảm ơn
Gurnard 14/11/11

Upvote, tùy chọn thứ ba ở đây là một phần quan trọng để hiểu ràng buộc / không ràng buộc của JS
SW4

sẽ myClick = function(event){...}được coi là một chức năng được đặt tên quá?
Daniel Möller

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

Hãy làm nó.


14
Thật tuyệt! Tài liệu arguments.calleedành cho các bên quan tâm: developer.mozilla.org/en/JavaScript/Reference/
mẹo

Cảm ơn, điều này đã giúp rất nhiều.
John O

2
Thật không may, điều này không hoạt động với ECMAScript 5 (2009) trở lên, từ liên kết MDN: "Phiên bản thứ 5 của ECMAScript (ES5) cấm sử dụng arguments.callee()trong chế độ nghiêm ngặt. Tránh sử dụng bằng arguments.callee()cách đặt tên biểu thức hàm hoặc sử dụng khai báo hàm trong đó một chức năng phải gọi chính nó. " (mặc dù nó đang sử dụng callee()thay vì callee, nó vẫn bị xóa, boo!)
Đại

59

Bạn có thể sử dụng một biểu thức hàm được đặt tên (trong trường hợp này là hàm được đặt tên abc), như vậy:

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 ...
}

Ví dụ làm việc nhanh và bẩn: http://jsfiddle.net/8qvdmLz5/2/ .

Thông tin thêm về các biểu thức hàm được đặt tên: http : // Khangax.github.io/nfe/ .


Tài giỏi. Một trong những trường hợp hiếm hoi mà NFE hữu ích. Cảm ơn.
DanMan

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

6

Nếu giải pháp của @ Cybernate không hoạt động, hãy thử ngắt kích hoạt chức năng của chính nó để bạn có thể tham khảo nó.

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

4

Nếu ai đó sử dụng jquery, anh ta có thể làm như thế này:

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

Hy vọng rằng nó có thể giúp đỡ một ai đó. Lưu ý rằng câu trả lời được đưa ra bởi @ user113716 hoạt động tốt :)


2

Tôi nghĩ rằng bạn có thể cần xác định chức năng xử lý trước thời hạn, như vậy:

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

Điều này sẽ cho phép bạn loại bỏ trình xử lý theo tên từ bên trong chính nó.


-4

Hãy thử điều này, nó làm việc cho tôi.

<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>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.