Удаление прослушивателей событий для автоматически созданных нескольких элементов

Я пытаюсь удалить прослушиватели событий из элементов после того, как они были нажаты, и хотя у меня, похоже, есть рабочее решение, оно не идеально, и я не уверен, почему оно работает иначе, чем сломанный код.

Хотя я понимаю, что есть более простые способы сделать это, это взято из класса JS, над которым я работаю, поэтому нужно сохранить часть структуры.

Это относится к предыдущему посту, на который я ответил правильно (но не работал, когда я расширил пример) - Удаление прослушивателей событий с анонимными вызовами функций в JavaScript.

В этом примере последний созданный div корректно удаляет прослушиватель, а более ранние — нет (поиграйте здесь — 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();

В версии, с которой я работал, я создаю массив, который содержит всех слушателей (скрипка здесь — 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);​

Последний работает нормально, но я уверен, что массив слушателей не нужен. Может быть, я слишком беспокоюсь, но я хотел бы знать оптимальное решение.


person Rich    schedule 06.04.2012    source источник


Ответы (2)


Вы должны сохранить каждого слушателя, если они не равны, поэтому вам нужна связь между слушателем и элементом. Поскольку элемент представлен объектом (DOM: объектная модель документа), вы можете добавить к ним пользовательские свойства (хотя это не рекомендуется: Могу ли я добавлять произвольные свойства к объектам DOM?) (демо):

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

Но поскольку вы используете один и тот же слушатель в каждом div, еще лучше не использовать отдельную функцию для каждого div, а одну и ту же (демо):

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);
}
person Zeta    schedule 06.04.2012
comment
Извините, глядя на мой вопрос, я действительно должен вернуть его в объектно-ориентированный контекст (причина, по которой слушатель находился в закрытии). Это работает, но не может быть применено к моему классу (моя вина в том, что я не показал все это должным образом). Спасибо, хотя - отредактирую вопрос! - person Rich; 06.04.2012

вы правы, вам не нужен массив, просто держите каждого слушателя в переменной, а затем передайте eventlistener в свою функцию удаления(),

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

обновлена ​​страница jsfiddle

person Okan Kocyigit    schedule 06.04.2012