Как передать объект в событие onclick

Возможный дубликат:
Обработчики событий внутри цикла Javascript - нужно закрытие?

Я получаю некоторый объект json через вызов API. Он имеет следующий формат:-

{data:[{id:"1",name:"some1",url:"someurl1"},{id:"2",name:"some2",url:"someurl2"}...]}

Я получаю его через результат jsonp, и он анализируется, как показано ниже:

function(results){
   for(var i=0;i<10;i++){
    item=document.createElement("div");
    item.innerHTML=results.data[i].name;
    item.onclick=function(){
        console.log(results.data[i]);  //--->this is where i am stuck 
      }
    }
 }

Как передать конкретный объект из цикла в событие onclick. Я имею в виду, что первый созданный div должен иметь событие onclick с данными первого объекта, а второй div должен содержать данные из второго объекта. Пожалуйста, спросите меня, требуется ли какое-либо разъяснение?

Изменить:- Если я сделаю что-то вроде этого:-

item.onclick=function(){
  console.log(results.data[1])
}

Я получаю этот конкретный объект в событии onclick всех предметов, но это не то, что я хочу

Изменить:- Вот как я наконец решил это. Благодаря ссылке, на которую указывает DCoder.

item.onclick =function(object){
           return function(){
           //do something with the object
           }

         }(obj);

6 ответов

Решение

Быстрое решение:

function(results){
    for(var i=0;i<10;i++){
        (function(index){ // create a closure, this makes a new scope
            item=document.createElement("div");
            item.innerHTML=results.data[index].name;
            item.onclick=function(){
                console.log(results.data[index]);  //--->this is where i am stuck 
            }
        })(i);  // pass in i
    }
}

Вы всегда можете использовать функцию данных jQuery для хранения и извлечения объекта данных:

function(results){
  for(var i=0;i<10;i++){
    item=document.createElement("div");
    item.innerHTML=results.data[i].name;

    // Store object in data 
    $(item).data("results", results.data[i]);

    item.onclick=function(){
        // Retrieve the data needed
        var data = $(this).data("results");
        console.log(data);
      }
    }
 }

Добавьте скрытое поле внутри вашего div (созданного в цикле), оставьте в нем все, что вы хотите. затем по клику div. найдите скрытое поле внутри него (div) и прочитайте его значение.

Событие onclick вызывается из jquery, когда кто-то нажимает на "элемент". Вы не можете ожидать пользовательских данных для обработчика событий, если они не запущены с использованием функции триггера.

Я бы лично использовал $.map поэтому функция обратного вызова создает новый контекст выполнения для каждой итерации.

Поскольку вы пометили вопрос с помощью jQuery, ваш код может быть таким простым, как:

$($.map(data, function(v, i) {
    return $('<div>').html(data[i].name).click(function() {
        console.log(data[i]);
    });
})).appendTo('body'); //appending for demonstration purposes

скрипка

Конечно, вы должны обернуть его внутри функции и передать data массив объектов, как вы делали ранее.

У вас проблемы с асинхронными вызовами внутри js. Это распространенная проблема, и она описана здесь: http://dojo-toolkit.33424.n3.nabble.com/Advice-on-closures-and-retaining-variable-values-inside-async-handlers-e-g-xhrGet-td3227726.html

В основном значение i равно 9 к тому времени, когда ваш console.log фактически запустится.

Есть много способов решить эту проблему в целом, но ваше конкретное решение, вероятно, должно состоять в огромной реструктуризации. Рассмотрим эту альтернативу (требуется jQuery), но мы могли бы сделать то же самое без нее очень легко.

$.each(results, function(data) {
  var $el = $("<div></div>").html(data.name).click(function() { console.log(data) });
})

Но было бы еще лучше использовать jQuery.data() для хранения вещей, а затем использовать .on() или же .delegate() слушать события клика как это

$.each(results, function(data) {
  var $el = $("<div></div>").addClass("yourThing").html(data.name).data("data", data);
})

// replace window with a closer parent if one exists
$(window).on("click", ".yourThing", function() {
   console.log($(this).data("data")); // retrieve data from jquerys .data() store
});
Другие вопросы по тегам