Динамически изменять событие HTML DOM - PullRequest
1 голос
/ 17 ноября 2009

Я пытаюсь динамически изменить событие onClick элемента, и у меня есть что-то вроде следующего:

for (var i = 1; i < 5; i++)
{
    getElementById('element' + i).onclick = function() { existingFunction(i); return false; };
}

Кажется, что все работает нормально, за исключением того факта, что аргумент, переданный функции'istingFunction () ', является конечным значением i = 4 при каждом его вызове. Есть ли способ привязать функцию к onclick, которая использует значение i во время привязки, в отличие от того, что она делает в данный момент и ссылается на оригинал i в цикле for.

Также есть ли способ выполнить одну и ту же привязку без необходимости каждый раз создавать анонимные функции? чтобы я мог напрямую ссылаться на «существующую функцию» в каждом клике по соображениям производительности?

Ура, ребята, О

Ответы [ 4 ]

4 голосов
/ 17 ноября 2009

Изменение

for (var i = 1; i < 5; i++)
{
    getElementById('element' + i).onclick = function() { existingFunction(i); return false; };
}

до

for (var i = 1; i < 5; i++)
{
    getElementById('element' + i).onclick = createOneHandler(i);
}

function createOneHandler(number){  
    return function() {  
        existingFunction(number); 
    }  
}

и должно работать нормально.

Рабочая демоверсия

Хорошее объяснение дано здесь

JavaScript, время для закрытия

1 голос
/ 17 ноября 2009

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

лучший код будет

for (var i = 1; i < 5; i++)
{
    getElementById('element' + i).onclick = existingFunction;
}

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

function existingFunction(event){
  // DO something here
}

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

Последнее, я советую вам использовать JS Framework (Jquery, ExtJS, DOJO, Prototype ...), потому что это упростит вашу задачу

1 голос
/ 17 ноября 2009

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

другой вопрос: все, что вы можете сделать, это разгрузить многословие с помощью

var f = function (i) { return function () { existingFunction(i); return false; } }
for (...) { document.getElementById(...).onclick = f(i); }

Кстати, вы должны использовать что-то вроде jQuery для манипулирования DOM (краткий синтаксис) и, возможно, Zeta (http://codex.sigpipe.cz/zeta/) для композиции функций

var f = compose(false_, existingFunction);
for (...) { $(...).click(f(i));
0 голосов
/ 17 ноября 2009

Ура! Это снова замыкание петли! См. 422784 , 643542 , 1552941 и др. Для дальнейшего обсуждения.

Есть ли способ выполнить одну и ту же привязку без необходимости каждый раз создавать анонимные функции?

Да, в пятом издании ECMAScript вы получаете function.bind:

for (var i = 1; i < 5; i++)
    document.getElementById('element'+i).onclick= existingFunction.bind(window, i);

Между тем, поскольку браузеры пока еще не поддерживают его, вы можете обезопасить альтернативную реализацию bind (см. нижнюю часть этого комментария для одного такого), построенную из анонимных функций, например запасной вариант.

В качестве альтернативы, назначьте одну и ту же функцию-обработчик события каждому элементу и просто посмотрите на this.id, чтобы увидеть, какой это номер элемента.

...