2013-05-11 3 views
0

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

for(var key in companies) { 
    $(document.createElement("span")) 
     .attr({ id: key }) 
     .appendTo($("#someDiv")) 
     .click(function() { 
      alert(key); 
     }); 
     $("#"+key).html("<b>" + key + "</b>: $"+companies[key]+"<br>"); 
    } 

Однако, когда я нажимаю на каком-либо из вновь образованных span элементов, я получаю предупреждение последнего значения в companies. Например, если бы я заявил:

var companies = { 
    "Google": 3, 
    "Apple": 4 
}; 

затем нажав на оба Google span и Apple, span предупредит 4. Мое желание - нажать на Google span, чтобы предупредить 3.

ответ

1

Вы должны захватить значение key с крышкой, так как петля будет закончена к тому времени click обработчика фактически выполняет. Попробуйте это:

.click((function() { 
    return function() { 
     alert(key); 
    }; 
})()); 

Или, вы можете просто alert его id, так как это то, что вы установите его, как:

.click(function() { 
    alert(this.id); 
}); 
+0

Почему возврат функции, вызывающей 'alert (key)', дает другое поведение, чем просто вызов 'alert (key)'? –

+0

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

3

Как об этом: -

Присоединить обработчик события с помощью delagtion событий с on() только один раз. (См. Класс добавлен compName). и просто используя его id.

См. Делегированное обращение обработчика событий here. Если somediv уже существуют в DOM, то вы можете просто использовать $('#someDiv').on('click','.compName',function(){...

$(function(){ 
$(document).on('click','.compName',function(){ 
//..... 
    alert(this.id); 
//.... 
}); 
.... 
for(var key in companies) { 
    $(document.createElement("span")) 
     .attr({ id: key, 'class':'compName' }).html("<b>" + key + "</b>: $"+companies[key]+"  
     <br>").html("<b>" + key + "</b>: $"+companies[key]+"<br>"). 
     .appendTo($("#someDiv")); 

    } 
//... 
}) 
+0

Нет причины, чтобы использовать 'document' для делегированного контейнера событий - все элементы добавлен в '# someDiv', поэтому я думаю, что можно использовать – Ian

+1

. Почему бы вам использовать делегирование событий при создании элемента на следующей строке? – adeneo

+0

@adeneo, почему вы хотите присоединить событие к каждому элементу, вместо этого yu может просто присоединяться к одному из родителей и делегировать его. – PSL

0

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

for(var key in companies) { 
    $(document.createElement("span")) 
     .attr({ id: key }) 
     .appendTo($("#someDiv")) 
     .click((function(privatekey) { 
      return function(){ 
       alert(privatekey); 
       }; 
     })(key)); 
     $("#"+key).html("<b>" + key + "</b>: $"+companies[key]+"<br>"); 
    } 
Смежные вопросы