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

6 回答 6

2

您总是可以使用 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);
      }
    }
 }
于 2012-09-19T20:10:07.593 回答
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
    }
}
于 2012-09-19T20:13:51.630 回答
0

当有人单击“项目”时,会从 jquery 触发 onclick 事件。除非使用触发器函数触发,否则您不能期望事件处理程序的自定义数据。

于 2012-09-19T19:59:05.853 回答
0

在 js 中进行异步调用时遇到了麻烦。这是一个常见问题,在此处进行了描述:http: //dojo-toolkit.33424.n3.nabble.com/Advice-on-closures-and-retaining-variable-values-inside-async-handlers-eg-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
});
于 2012-09-19T20:06:46.830 回答
0

在您的 div 中添加一个隐藏字段(在循环中创建),保留您想要的任何内容。然后点击div。找到其中的隐藏字段(div)并读取其值。

于 2012-09-19T20:14:13.940 回答
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

小提琴

当然,您必须将它包装在一个函数中并data像以前一样传递对象数组。

于 2012-09-19T20:20:07.233 回答