如何将一个对象传递给onclick事件

4

可能是重复的问题:
JavaScript循环内部的事件处理程序 - 需要闭包吗?

我通过API调用获取了一些JSON对象。它的格式如下:

{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);

3
这是臭名昭著的JavaScript闭包问题。 - SLaks
一个人在变得疯狂之前可以回答这个问题多少次? - Shmiddty
@Shmiddty请再试一次... - noname
@DCoder真的很有帮助..如果你当初把这个作为答案发表,我就可以接受它了.. - noname
6个回答

2
你可以始终使用 jQuery 的 data 函数来存储和检索数据对象:
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);
      }
    }
 }

2

快速解决方案:

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
    }
}

谢谢Shmiddty,这确实是我最终解决问题的最接近方法。 - noname
但是你明白为什么一开始会出现这个问题吗? - Shmiddty

0

你在JS中进行异步调用时遇到了麻烦。这是一个常见的问题,可以在这里找到解决方法: http://dojo-toolkit.33424.n3.nabble.com/Advice-on-closures-and-retaining-variable-values-inside-async-handlers-e-g-xhrGet-td3227726.html

基本上,i的值在你的console.log实际运行时等于9

通常有许多方法来解决这个问题,但你的具体解决方案可能需要重新架构。考虑这个替代方案(需要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
});

0

我个人会使用$.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

Fiddle

当然,你需要将它包装在一个函数中,并像之前一样传递data对象数组。


0

当有人点击“项”时,onclick事件将从jquery触发。除非使用trigger函数触发,否则不能期望将自定义数据传递给事件处理程序。


1
你误解了问题。 - SLaks

0
在循环中创建div时,向其中添加一个隐藏字段,并将所需内容保存在其中。然后,在单击div时,查找其中的隐藏字段并读取其值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接