如何将值传递给jQuery单击回调?

时间:2012-11-07 05:19:20

标签: javascript jquery callback

如果我像这样在循环中创建一堆对象:

for(var i = 0; i < 5; i++)
{
    var data = { val: i * 2 };
    var obj = $('<li>Item</li>');

    $("ul").append(obj);

    obj.click(function()
    {
        alert(data.val);
        // Output is 8 for all items.

    });
}

我只能访问data处理程序中最后创建的.click()对象。

如何引用处理程序中的相关data对象 - 与单击jQuery对象同时创建的对象?

我过去能够通过.attr()通过var data = { val: i * 2 }; var obj = $('<li>Item</li>'); obj.data = data; obj.click(function() { // 'data' is undefined here i.e. not associated with $(this). alert($(this).data.val); }); 分配jQuery对象的随机属性来保存数据而不是单独的对象,但我想摆脱这种方法

我也试过这个,但没有运气:

{{1}}

2 个答案:

答案 0 :(得分:2)

第一个例子的问题被变量的范围所掩盖。在JS中,所有变量都有函数作用域,因此重写代码以显示更明确的变量:

var i,data,obj;
for(i = 0; i < 5; i++) {
    data = { val: i * 2 };
    obj = $('<li>Item</li>');

    $("ul").append(obj);
    obj.click(function() {
        alert(data.val);
    });
}

现在更明显的是,循环中的data只是一个变量,而不是每个迭代的新变量(如Java,C#等)。单击处理程序使用此变量时传递的匿名函数将关闭它。结果是使用函数执行时变量的当前值,而不是当函数被指定为单击处理程序时变量的值。

要解决此问题,您可以将数据附加到元素本身。

在您的代码中,您执行obj.data = ...但是将值附加到选择而不是元素。下次选择相同的元素时,您将拥有一个没有data.property的新对象。相反,您可以使用jQuery .data()方法。

obj.data('key',data);
obj.click(function() {
    alert($(this).data('key').val);
});

或者如果你想将值嵌入到函数中,你可以使用自执行函数来实现。将变量作为参数传递给函数时,您使用当前值而不是关闭变量。

var i,
    data,
    obj,
    createClick = function(data) {
        return function(){
           alert(data.val);
        };
    };
for(i = 0; i < 5; i++) {
    data = { val: i * 2 };
    obj = $('<li>Item</li>');

    $("ul").append(obj);
    obj.click(createClick(data));
}

注意 另外,你应该养成将{放在一行而不是开头的习惯。如果{位于下一行,则半结肠插入可能会产生一些意外结果。 E.g

return 
    {
      val : 1
    }

可能返回undefined,因为在return忽略对象文字之后可能会插入一个分号

答案 1 :(得分:2)

您可以使用jQuery .data()方法。 http://api.jquery.com/data/

例如:

for(var i = 0; i < 5; i++){
    var obj = $('<li>Item</li>');
    obj.data('myData', {first: i * 2, second: i * 3});

    $("ul").append(obj);

    obj.click(function(){
        alert($(this).data('myData').first);
        alert($(this).data('myData').second);
    });
}