Javascript: генерировать динамически обработчик

Я программирую на Javascript.

Мне нужно динамически генерировать обработчики событий для onclick событие.

Здесь над кодом:

for (var i = 1; i < CurrValue; i++) {
    getId('btnReadRFIDTag_' + i).onclick = function () 
    {
        ReadRFIDTag(getId('txtCode_' + i));
    };

}

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

Но я не могу решить проблему, потому что обработчик не позволяет параметры для функции.

Как я могу решить эту проблему?

Спасибо.

Хорошего дня.

1 ответ

Решение

Три варианта:

Используйте функцию Builder

Обычный способ - создать функцию-обработчик для обработчиков:

for (var i = 1; i < CurrValue; i++) {
    getId('btnReadRFIDTag_' + i).onclick = buildHandler(i);
}
function buildHandler(index) {
    return function() {
        ReadRFIDTag(getId('txtCode_' + index));
    };
}

Функция построена buildHandler закрывается над index аргумент от этого вызова buildHandler, а не более iи поэтому он видит правильное значение.

Используйте ES5 Function#bind

Если вы можете положиться на ES5 (или вы используете шайбу ES5, так как это функция с возможностью подбора), вы можете сделать это с Function#bind:

// Using Function#bind (option 1)
for (var i = 1; i < CurrValue; i++) {
    var elm = getId('btnReadRFIDTag_' + i);
    elm.onclick = function(index) {
        ReadRFIDTag(getId('txtCode_' + index));
    }.bind(elm, i);
}

При таком использовании он создает ненужные дополнительные функции, поэтому вы также можете использовать его следующим образом:

// Using Function#bind (option 2)
for (var i = 1; i < CurrValue; i++) {
    var elm = getId('btnReadRFIDTag_' + i);
    elm.onclick = myHandler.bind(elm, i);
}

function myHandler(index) {
    ReadRFIDTag(getId('txtCode_' + index));
}

Использовать делегирование событий

Вместо того, чтобы помещать обработчик на каждую кнопку, если они все находятся в контейнере (и в конечном счете, конечно, они есть, даже если это просто document.body), вы можете поместить обработчик в этот контейнер, а затем использовать event.target чтобы узнать, какая кнопка была нажата. Я бы не стал делать это со старым стилем onclick, но вы можете с addEventListener или же attachEvent:

var container = /* ...get the container... */;
if (container.addEventListener) {
    container.addEventListener('click', clickHandler, false);
}
else if (container.attachEvent) {
    container.attachEvent('onclick', function(e) {
       return clickHandler.call(this, e || window.event);
    });
}
else {
    // I wouldn't bother supporting something that doesn't have either
}

function clickHandler(e) {
    var btn = e.target;
    while (btn && btn !== this && btn.id.substring(0, 15) !== "btnReadRFIDTag_") {
        btn = btn.parentNode;
    }
    if (btn && btn !== this) {
        ReadRFIDTag(getId('txtCode_' + btn.id.substring(15)));
    }
}

Способ, который работает, заключается в подключении click событие в контейнере, а затем, когда клик поднимается (вниз?) к нему, он смотрит, откуда произошел щелчок, и определяет, является ли это (или его предок) одной из кнопок, о которых мы заботимся. Если это так, мы действуем на это.

Другие вопросы по тегам