简体   繁体   中英

Removing event listeners on automatically created multiple elements

I'm trying to remove event listeners from elements after they've been clicked on and although I seem to have a working solution, it's not ideal and I'm not sure why it works differently to the broken code.

Although I realise there are simpler ways of doing this, this is taken from a JS class I'm working on so need to retain some of the structure.

This relates to a previous post I made which was answered correctly (but didn't work when I expanded the example) - Removing event listeners with anonymous function calls in JavaScript .

In this example, the last created div removes the listener correctly but earlier ones don't (fiddle here - http://jsfiddle.net/richwilliamsuk/NEmbd/ ):

var ctnr = document.getElementById('ctnr');
var listener = null;

function removeDiv (d) {
    alert('testing');
    d.removeEventListener('click', listener, false);
}

function addDiv () {
    var div = document.createElement('div');
    div.innerHTML = 'test';
    ctnr.appendChild(div);
    div.addEventListener('click', (function (d) { return listener = function () { removeDiv(d); } })(div), false);
}

addDiv();
addDiv();
addDiv();

In the version I got working I create an array which holds all the listeners (fiddle here - http://jsfiddle.net/richwilliamsuk/3zZRj/ ):

var ctnr = document.getElementById('ctnr');
var listeners = [];

function removeDiv(d) {
    alert('testing');
    d.removeEventListener('click', listeners[d.id], false);
}

function addDiv() {
    var div = document.createElement('div');
    div.innerHTML = 'test';
    ctnr.appendChild(div);
    div.id = listeners.length;
    div.addEventListener('click', (function(d) {
        return listeners[listeners.length] = function() {
            removeDiv(d);
        }
    })(div), false);
}


addDiv();
addDiv();
addDiv();

document.getElementById('btn').addEventListener('click', function() {
    alert(listeners);
}, false);​

The final one works fine but I'm sure the listener array shouldn't be necessary. Maybe I'm worrying too much but I'd like to know the optimal solution.

you are right, you don't need an array, just hold every listener in a variable, than pass eventlistener in your remove() function,

var ctnr = document.getElementById('ctnr');

function removeDiv(d, ev) {
    alert('testing');
    d.removeEventListener('click', ev, false);
}

function addDiv() {
    var div = document.createElement('div');
    div.innerHTML = 'test';
    ctnr.appendChild(div);
    div.addEventListener('click', (function(d) {
        var myfunc;
        return myfunc = function() {
            removeDiv(d, myfunc);
        }
    })(div), false);
}


addDiv();
addDiv();
addDiv();

document.getElementById('btn').addEventListener('click', function() {
    alert(listeners);
}, false);​​

updated jsfiddle page

You have to save each and every listener if they are unequal, so you need a relation between listener and element. Since an element is represented by an object (DOM: document object model) you can add custom properties to them (although it's not recommended: Can I add arbitrary properties to DOM objects? ) ( demo ):

var ctnr = document.getElementById('ctnr');

function removeDiv (d) {
    alert('testing');
    d.removeEventListener('click', d.custom_Listener , false);
}

function addDiv () {
    var div = document.createElement('div');
    div.innerHTML = 'test';
    div.custom_Listener = function(){removeDiv(this)};
    ctnr.appendChild(div);
    div.addEventListener('click', div.custom_Listener , false);
}

But since your using the same listener in every div its even better not to use a separate function for every div but the same ( demo ):

var ctnr = document.getElementById('ctnr');
var listener = function(){
    removeDiv(this);
};

function removeDiv (d) {
    alert('testing');
    d.style.backgroundColor = '#36f';
    d.removeEventListener('click', listener, false);
}

function addDiv () {
    var div = document.createElement('div');
    div.innerHTML = 'test';
    ctnr.appendChild(div);
    div.addEventListener('click', listener , false);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM