问题描述:

I'm looking at transferring existing functionality (built with PrototypeJS) to jQuery and have been working through a couple of examples.

One example I'm a bit stuck on, specifically with regards to binding functions (and values) to an event. This example tries to apply a mouseover event, with an incremented value to a list of links. The value that is alerted I want to be the same every time (so link 1 alerts "1", link 2 alert "2" etc etc)

Here's a snippet of a simple example.

Prototype:

findLinks: function () {

i = 1;

$$("#vertical-content-links ul li a").each(function (s) {

Event.observe(s, "mouseover", this.activateLink.bindAsEventListener(this, i))

i++

}.bind(this))

},

activateLink: function (e, i) {

alert(i)

}

Within this example, when link 1 is mouseovered, it will always alert "1". Link 2 will always alert "2" etc etc as it is alerting the value of i when the function is applied to that event.

However, my similar code in jQuery....

findLinks: function () {

i = 1;

$("#vertical-content-links ul li a").each(function (s, elmt) {

$(elmt).bind("mouseover", function (e) {

_this.activateLink(i);

i++

})

})

},

activateLink: function (i) {

alert(i);

}

(Note: _this is a closure specified elsewhere in the code)

When this runs, every time a link is mouseovered, the value of i is incremented by one, so link 1 will alert 1, then 2,3,4,5 etc as the value of i doesn't seem to be bound to the function when it is applied to the event

Hope that makes sense

Does anyone know a way around this so it works more the way Prototype does. I really want to start using jQuery more but need to understand this issue first.

Cheers

网友答案:

I bet that i gets incremented because you put i++ inside the mouseover handler. Carry it out and try this:

findLinks: function() {
    var i = 1;
    $("#vertical-content-links ul li a").each(function(s, elmt) {
        var j = i++;
        $(elmt).bind("mouseover",function(e) {
            _this.activateLink(j);
        })
    })
},
网友答案:

.each() already forms a closure here, so just use the iterator it already has, your s variable, like this:

$("#vertical-content-links ul li a").each(function (s, elmt) {
    $(elmt).bind("mouseover", function (e) { //or just .mouseover(function() {
        _this.activateLink(s+1);             //0-based index, so add 1
    });
});

Try out a demo here. The first argument of the .each() callback function is the index of the element in the matches set, and since it's passed into the closure you don't have to worry about referencing the same changing i variable like you currently have.

相关阅读:
Top