วิธี removeEventListener ที่เป็น addEventListener พร้อมฟังก์ชัน anonymous?


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

คำตอบ:


111

คุณทำไม่ได้ คุณต้องใช้ฟังก์ชันที่มีชื่อหรือจัดเก็บข้อมูลอ้างอิงไว้

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

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

อัปเดต:

คุณสามารถสร้างตัวจัดการตัวจัดการของคุณเอง (:)):

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

จากนั้นคุณสามารถใช้กับ:

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

var handler = doSomethingWith('Test. ');

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

การสาธิต


คุณช่วยอธิบายได้ไหมว่าโครงสร้างคืออะไร? ทักษะภาษาอังกฤษของฉันไม่ดีพอที่จะเข้าใจ ... ขอบคุณ
Japboy

1
@Japboy: ยินดีต้อนรับ :) ฉันเพิ่งสังเกตเห็นข้อผิดพลาดเล็กน้อยและแก้ไขได้
Felix Kling

จะห่อ addListener กับ removeListener ทำไม?
ไร้ประโยชน์

@useless: คุณหมายถึงฟังก์ชันเรียกตัวเองหรือไม่? เพื่อรักษาiและlisteners"ส่วนตัว"
Felix Kling

2
@Bergi: เสร็จแล้ว แจ้งให้เราทราบหากพลาดอะไรไป
Felix Kling

11

คุณทำไม่ได้คุณต้องมีการอ้างอิงถึงฟังก์ชัน:

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

คุณส่งผ่านวัตถุเหตุการณ์ได้อย่างไร
slier

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

5

คุณสามารถทำได้เช่นนั้น:

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

จากนั้นคุณสามารถลบตัวฟังเหตุการณ์ได้ดังนี้:

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

// Remove event listener
disposer();

เป็นไปได้หรือไม่ที่จะระบุว่าเหตุการณ์ใดที่ถูกผูกไว้กับวัตถุเช่นนี้?
frumbert

คุณสามารถเพิ่มคุณสมบัติบางอย่างให้กับฟังก์ชันเช่นประเภทขอบเขตเป็นต้นconst disposerFn = () => { scope.removeEventListener(type, handler, capture); } disposerFn.type = type; return disposerFn;
Simon Jentsch

1

หากคุณไม่จำเป็นต้องรองรับ IE คุณสามารถใช้ตัวเลือกครั้งเดียว

[Element].addEventListener('click', () => {...}, {
  capture: false,
  once: true
});
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.