1

There is such DOM structure:

<div class="info" id="step1">
<a href="#" id="next_step_1"> ok </a>
</div>

<div class="info" id="step2">
<a href="#" id="next_step_2"> ok </a>
</div>

<div class="info" id="step3">
<a href="#" id="next_step_3"> ok </a>
</div>

... (so on)

Div .info has display:none property (except 1), so what I want to achieve: when I click ok, this div fades out, next div fades in.

Of course, that's not DRY to write function to each div, so I tried this:

  for (var i=1; i<5; i++){
       $("body").delegate('#next_step_'+i, 'click', function(){
       $("#step"+i).fadeOut();
       $("#step"+i+1).fadeIn();
       });

    }

This code didn't work, and I tried:

  for (var i=1; i<5; i++){
       $("body").delegate('#next_step_'+i, 'click', function(){
       alert("#step"+i)
       });

    }

And alert worked(so on delegate i was 1) but alert was #step5.

That confuses me, I supposed JS output 5 functions for each div... Help me get this around.

4

2 回答 2

7

Why don't you just use the class info? It saves separately assigning a delegation functions

$("body").delegate(".info", 'click', function(){
    $(this).fadeOut();
    $(this).next().fadeIn();
});
/*
    As of jQuery 1.7+ 
    $("body").on("click", ".info", function(){
        $(this).fadeOut();
        $(this).next().fadeIn();
    });
*/

Also, as of jQuery 1.7+ you should be using .on(). on combines the bind, live, and delegate functions.

You code doesn't work because of an closure issue:

for (var i = 0; i < 5; i++) {
    (function (i) {
        $("body").delegate('#next_step_' + i, 'click', function () {
            alert("#step" + i)
        });
    })(i);
}

I can't really explain it. I just know I had an issue like this and I got it fixed using that (See). I still encourage using the first method.

于 2013-07-19T03:19:43.340 回答
5

delegate has been superseeded by on as of 1.7.0

Use on to delegate the events instead

Try this

$("body").on('click', '.info', function(){
    var $this = $(this);      
    $this.nextAll('.info').first().fadeIn();
    $this.fadeOut();
});

Working fiddle

You code does not work as because of classic closure issue. The value of i will be shared by all instances of events as , events happen at a later time. So i will always be the value of the last iteration.

Your example

I prefer this than binding it in IFFY

 for (var i = 1; i < 5; i++) {
        $("body").delegate('#next_step_' + i, 'click', bindClick(i));
    }

    function bindClick(i) {
        return function() {
            alert("#step"+i)
        }
    }

When you return a function , the function forms a closure , saving the state of the outermost variables at the time the function was bound creating a new scope that is unique to the function that is returned. As the variables are tied to the scope you can access the right values.

If you have a difficult time understanding the above method the same can be written as as IIFE( Immediately Invoked Function Expression), that is executing the function immediately that creates a new scope for the variables in which it is executed, which is what shawn has written.

Check Fiddle

But in your case you are trying to access the variable that is common to all the handlers.

于 2013-07-19T03:23:22.343 回答