Jump to content
  • 0

removeEventListener в цикле


Great Rash
 Share

Question

Замучился уже...

Есть таблица, на каждую ячейку которой я повесил событие 'click'. При наступлении некоего события мне нужно удалить обработчик 'click' со всех ячеек. Бегу по таблице циклом вот так:

var r = table.rows;

for (var i = 0, len = r.length; i < len; i++) {
var c = r[i].cells;

for (var j = 0, len2 = c.length; j < len2; j++) {
c[j].removeEventListener('click', handler, false);
}
}

/*
* листенер, естественно, удаляется только у последнего элемента
* т.к. нужно замыкание
* пробую его
*/

var r = table.rows;

for (var i = 0, len = r.length; i < len; i++) {
var c = r[i].cells;

for (var j = 0, len2 = c.length; j < len2; j++) {
(function(i, j) {
c[j].removeEventListener('click', handler, false);
})(i, j);
}
}

// такая же фигня

Вопрос: что я не так делаю? Почему листенер удаляется только у последней ячейки?

Link to comment
Share on other sites

10 answers to this question

Recommended Posts

  • 0

Вот так:

var t = document.createElement('table');

for (var i = 0, len = obj.length; i < len; i++) {
var r = t.insertRow(i);

for (var j = 0, len2 = obj.length; j < len2; j++) {
(function(i) {
var c = r.insertCell(j);

var handler = function() {
someFunc(params);
}

c.addEventListener('click', handler, false);
})(i);
}
}

Link to comment
Share on other sites

  • 0
Вот так:

var t = document.createElement('table');

for (var i = 0, len = obj.length; i < len; i++) {
var r = t.insertRow(i);

for (var j = 0, len2 = obj.length; j < len2; j++) {
(function(i) {
var c = r.insertCell(j);

var handler = function() {
someFunc(params);
}

c.addEventListener('click', handler, false);
})(i);
}
}

handler может существовать только в контексте замыкания, и ссылка на эту функцию может отсутствовать, так как он находится в локальной зоне видимости замыкания.

Как совет, попробуй проверить в коде с удалением лиснера, существует ли такая функция handler

Link to comment
Share on other sites

  • 0

Вообще я упрощенный вариант написал,т.к. кода дофига... у меня на самом деле объект и handler хранится в объекте вот так:

var self = this;
var t = document.createElement('table');

for (var i = 0, len = obj.length; i < len; i++) {
var r = t.insertRow(i);

for (var j = 0, len2 = obj.length; j < len2; j++) {
(function(i) {
var c = r.insertCell(j);

self.handler = function() {
someFunc(params);
}

c.addEventListener('click', self.handler, false);
})(i);
}
}

И да, я проверял существование handler'a - он есть. Листенер же удаляется, но только у последней ячейки (будто замыкания вообще нет...)

Link to comment
Share on other sites

  • 0
Вообще я упрощенный вариант написал,т.к. кода дофига... у меня на самом деле объект и handler хранится в объекте вот так:

И да, я проверял существование handler'a - он есть. Листенер же удаляется, но только у последней ячейки (будто замыкания вообще нет...)

Дык, скорее всего его и нет :)

Сделай вот так

function( i ) { return function(){ alert(i) } }(i)

А вообще, замыкания в данном случае зло.

Куда проще присвоить свойство ячейке и работать с ним.

А вообще можно использовать cellIndex, если его будет достаточно.

Link to comment
Share on other sites

  • 0

Написал:

var self = this;
var r = table.rows;

for (var i = 0, len = r.length; i < len; i++) {
var c = r[i].cells;

for (var j = 0, len2 = c.length; j < len2; j++) {
(function(i) {
return function(){alert(i);}

c[j].removeEventListener('click', self.handler, false);
})(i);
}
}

Алерта нет.

Ячейке свойства тоже пробовал присваивать вот так:

var self = this;
var r = table.rows;

for (var i = 0, len = r.length; i < len; i++) {
var c = r[i].cells;

for (var j = 0, len2 = c.length; j < len2; j++) {
c[j].I = i;
c[j].J = j;

table.rows[c[j].I]cells[c[j].J].removeEventListener('click', self.handler, false);
}
}

Link to comment
Share on other sites

  • 0
Написал:

Не то, тут этот метод не прокатит.

Замыкание в данном случае не будут работать.

Замыкания создают анонимную функцию. Так как она анонимная, то сделать ссылку на нее ты не сможешь.

Используй другие методы работы, без замыканий.

Вот тебе один из вариантов решения проблемы


var handler = function() {
alert(this.cellIndex);
}

var t = document.createElement('table');

for (var i = 0, len = 2; i < len; i++) {
var r = t.insertRow(i);

for (var j = 0, len2 = 3; j < len2; j++) {
(function(i) {
var c = r.insertCell(j);


c.addEventListener('click', handler , false);
c.innerHTML = j;
})(i);
}
}

document.body.appendChild( t );

var r = t.rows;

for (var i = 0, len = r.length; i < len; i++) {
var c = r[i].cells;

for (var j = 0, len2 = c.length; j < len2; j++) {
// c[j].removeEventListener('click', handler, false);
}
}

Edited by s0rr0w
Link to comment
Share on other sites

  • 0
Хм, и правда заработало! Спасибо большое. Только я не понимаю почему?

addEventListener в качестве слушателя принимает ссылку на функцию. А при удалении ему нужно указывать снова же ссылку на эту самую функцию. Функции с одинаковыми именами и содержимым не добавляются несколько раз.

Так вот, при замыканиях создается анонимная функция, а сослаться на нее ты уже не сможешь, так как у нее нет имени. Это как писать письма анонимному читателю.

В моем примере часть кода даже лишняя, ее можно убрать, чтобы не вызывать путаницу

for (var i = 0, len = 2; i < len; i++) {
var r = t.insertRow(i);

for (var j = 0, len2 = 3; j < len2; j++) {
var c = r.insertCell(j);
c.addEventListener('click', handler , false);
c.innerHTML = j;
}
}

Далее, если ты не заметил, то я обращаюсь к внутреннему свойству ячейки cellIndex а не к j. Это даже более правильно, так как после перестановки двух ячеек местами у тебя сохранится нормальный порядок ячеек, а не 1, 3, 2, 4 например.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. See more about our Guidelines and Privacy Policy