简体   繁体   English

jQuery click事件的Javascript变量范围问题

[英]Javascript variable scope issue with jquery click event

I am trying to assign a series of objects stored in an array to jquery click event handlers. 我试图将存储在数组中的一系列对象分配给jquery click事件处理程序。

The problem is , when the event fires, I only ever references the last object in the array. 问题是,事件触发时,我只引用了数组中的最后一个对象。

I have put together a simple example to show the problem: 我整理了一个简单的例子来说明问题:

function dothis() {
    this.btns = new Array('#button1', '#button2');
}

// Add click handler to each button in array:
dothis.prototype.ClickEvents = function () {

    //get each item in array:
    for (var i in this.btns) {

        var btn = this.btns[i];
        console.debug('Adding click handler to button: ' + btn);

        $(btn).click(function () {
            alert('You clicked : ' + btn);
            return false;
        });
    }
}

var doit = new dothis();
doit.ClickEvents();

The HTML form contains a couple of buttons: HTML表单包含几个按钮:

<input type="submit" name="button1" value="Button1" id="button1" />
<input type="submit" name="button2" value="Button2" id="button2" />

When button1 is clicked, it says "You clicked #Button2" 单击button1时,它会显示“您单击了#Button2”

It seems that both button click handlers are pointing to the same object inside var btn. 似乎两个按钮单击处理程序都指向var btn中的同一对象。

Considering the variable is inside the for loop, I cannot understand why. 考虑到变量在for循环中,我不明白为什么。

Any ideas? 有任何想法吗?

You need a function factory to close the loop variable, such as this: 您需要一个函数工厂来关闭循环变量,例如:

//get each item in array:
for (var i=0; i<this.btns.length; i++) {

    $(this.btns[i]).click(function(item) { 
        return function () {
            alert('You clicked : ' + item);
            return false;
        }
    }(this.btns[i]));

}

Another good option is to let jquery help you. 另一个不错的选择是让jquery帮助您。 Use jQuery.each(). 使用jQuery.each()。 The variable btn here is local to the handler function, and so isn't reused between iterations. 此处的btn变量是处理程序函数的局部变量,因此不会在两次迭代之间重用。 This allows you to close it and have it keep its value. 这使您可以关闭它并保持其价值。

$.each(this.btns, function() {
    var btn = this;
    $(this).click(function () {
        alert('You clicked : ' + btn);
        return false;
    }
});

within an event handler, 'this' usually refers to the element firing the event, in this case, it would be your button 在事件处理程序中,“ this”通常是指触发事件的元素,在这种情况下,它将是您的按钮

so the solution to your problem is fairly easy, instead of referencing the btn variable, which lives in a higher scope and gets mutated long before the event handler fires, we simply reference the element that fired the event and grab its ID 因此,解决问题的方法非常简单,我们无需引用btn变量,该变量位于较高的作用域中,并且在事件处理程序触发之前很长一段时间就发生了变异,我们只需引用触发事件的元素并获取其ID

$(btn).click(function () {
  alert('You clicked : #' + this.id);
  return false;
});

Note: if your array contains other selectors that just the ID, this will obviously not reflect that and simply continue to show the ID 注意:如果您的数组包含仅ID的其他选择器,则显然不会反映出来,而只是继续显示ID

Lucky, the click handler (and all other event handlers afaik) take an extra parameter for eventData, useful like so: 幸运的是,单击处理程序(以及所有其他事件处理程序afaik)为eventData附加了一个参数,如下所示很有用:

$(btn).click(btn, function (event) {
  alert('You clicked : #' + event.data);
  return false;
});

User an array if you're passing multiple things: 如果要传递多个内容,请使用一个数组:

$(btn).click(['foo', 'bar'], function (event) {
  alert('this should be "foo": ' + event.data[0]);
  alert('this should be "bar": ' + event.data[1]);
  return false;
});

Your problem is here: 您的问题在这里:

alert('You clicked : ' + btn);

btn retains the value from the last time it was called in the loop. btn保留从上次在循环中调用它以来的值。 Read the value from the button in the event. 在事件中从按钮读取值。

    $(btn).data('selector', btn).click(function () {
        alert('You clicked : ' + $(this).data('selector'));
        return false;
    });

http://jsfiddle.net/Mc9Jr/1/ http://jsfiddle.net/Mc9Jr/1/

you have to use closures for this. 您必须为此使用闭包。 i'm not sure if i remember the correct syntax but you could try this: 我不确定我是否记住正确的语法,但是您可以尝试以下方法:

$(btn).click(function () {
    return function() {
        alert('You clicked : ' + btn);
        return false;
    }
});

maybe you need to change just the click binding: 也许您只需要更改点击绑定即可:

$(btn).click(function () {
    alert('You clicked : ' + $(this).attr('id'));
    return false;
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM