Làm cách nào để removeEventListener là addEventListener có chức năng ẩn danh?


88
function doSomethingWith(param)
{
    document.body.addEventListener(
        'scroll',
        function()
        {
            document.write(param);
        },
        false
    ); // An event that I want to remove later
}
setTimeout(
    function()
    {
        document.body.removeEventListener('scroll', HANDLER ,false);
            // What HANDLER should I specify to remove the anonymous handler above?
    },
    3000
);
doSomethingWith('Test. ');

Câu trả lời:


110

Bạn không thể. Bạn phải sử dụng một hàm được đặt tên hoặc lưu trữ tham chiếu bằng cách nào đó.

var handler;

function doSomethingWith(param) {
    handler = function(){
        document.write(param);
    };  
    document.body.addEventListener('scroll', handler,false);
}
setTimeout(function() {
     document.body.removeEventListener('scroll', handler ,false);
}, 3000);

Cách tốt nhất là thực hiện điều này theo cách có cấu trúc để bạn có thể xác định các trình xử lý khác nhau và xóa chúng. Trong ví dụ trên, rõ ràng bạn chỉ có thể loại bỏ trình xử lý cuối cùng.

Cập nhật:

Bạn có thể tạo trình xử lý trình xử lý của riêng mình (:)):

var Handler = (function(){
    var i = 1,
        listeners = {};

    return {
        addListener: function(element, event, handler, capture) {
            element.addEventListener(event, handler, capture);
            listeners[i] = {element: element, 
                             event: event, 
                             handler: handler, 
                             capture: capture};
            return i++;
        },
        removeListener: function(id) {
            if(id in listeners) {
                var h = listeners[id];
                h.element.removeEventListener(h.event, h.handler, h.capture);
                delete listeners[id];
            }
        }
    };
}());

Sau đó, bạn có thể sử dụng nó với:

function doSomethingWith(param) {
    return Handler.addListener(document.body, 'scroll', function() {
        document.write(param);
    }, false);
}

var handler = doSomethingWith('Test. ');

setTimeout(function() {
     Handler.removeListener(handler);
}, 3000);

BẢN GIỚI THIỆU


Bạn có thể giải thích cách cấu trúc là gì? Kỹ năng tiếng Anh của tôi không đủ tốt để hiểu điều đó ... Cảm ơn.
Japboy

1
@Japboy: Không có gì đâu :) Tôi chỉ nhận thấy một lỗi nhỏ và đã sửa nó.
Felix Kling

Tại sao bạn lại bọc addListener và removeListener?
vô ích,

@useless: Ý bạn là chức năng tự gọi? Để giữ ilisteners"riêng tư".
Felix Kling,

2
@Bergi: Đã xong. Hãy cho tôi biết nếu tôi bỏ lỡ điều gì đó.
Felix Kling

11

Bạn không thể, bạn cần tham chiếu đến hàm:

function doSomethingWith(param) {
   var fn = function(){ document.write(param); };
   document.body.addEventListener('scroll', fn, false);
   setTimeout(function(){ document.body.removeEventListener('scroll', fn, false); }, 3000);
}
doSomethingWith('Test. ');

làm thế nào để bạn vượt qua đối tượng sự kiện?
slier

@sliervar fn = function(event){ document.write(param); };
cychoi

5

Bạn cũng có thể làm điều này như vậy:

const ownAddEventListener = (scope, type, handler, capture) => {
  scope.addEventListener(type, handler, capture);
  return () => {
    scope.removeEventListener(type, handler, capture);    
  }
}

Sau đó, bạn có thể xóa trình nghe sự kiện như sau:

// Add event listener
const disposer = ownAddEventListener(document.body, 'scroll', () => { 
  // do something
}, false);

// Remove event listener
disposer();

Có thể xác định những sự kiện nào đã được ràng buộc trên đối tượng như thế này không?
frumbert

Bạn chỉ có thể thêm một số tính đến chức năng, giống như các loại, phạm vi, vvconst disposerFn = () => { scope.removeEventListener(type, handler, capture); } disposerFn.type = type; return disposerFn;
Simon Jentsch

1

nếu bạn không phải hỗ trợ IE, bạn có thể sử dụng tùy chọn một lần

[Element].addEventListener('click', () => {...}, {
  capture: false,
  once: true
});
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.