0

何よりもまず、助けてくれて、noobの質問を申し訳ありません。

for内のイベントに問題があります。DOMは次のようなものです。

<div class="wrap">

  <div class="trigger">...</div>
  <div class="trigger">...</div>

  <div class="box">...</div>
  <div class="box">...</div>

</div>

そして私のJSjQueryは次のとおりです。

for( i = 0; i < $('.trigger').length; i++ ){
$('.trigger:eq('+i+')').click(function(){
    $('.box:eq('+i+')').fadeIn();
});

$('.box:eq('+i+') .bt-close').click(function(){
    $('.box:eq('+i+')').fadeOut();
});
}

問題は、トリガーをクリックすると、iの値が2になることです。trigger1、trigger2 ...を使用したくないのは、最終バージョンでいくつになるかわからないためです。

4

4 に答える 4

4
function createEffects(index) {
    $('.trigger:eq(' + index + ')').click(function() {
        $('.box:eq(' + index + ')').fadeIn();
    });

    $('.box:eq(' + index + ')').click(function() {
        $('.box:eq(' + index + ')').fadeOut();
    });
}


for (i = 0; i < $('.trigger').length; i++) {

    createEffects(i);
}​

可能な場合はクロージャの使用を避けます。それらがない例を次に示します:http://jsfiddle.net/JBbQk/

于 2012-04-09T15:10:35.500 に答える
1

問題は閉鎖にあります。ループ内の関数は、iその値ではなく、その周りのスコープからの変数を記憶します。関数が呼び出されると、ループはすでに終了しており、変数値は最後の値です。代わりに、関数が値自体を取得するようにします。これを行う通常の方法は、別の変数を使用することです。@JoeTuskanが示すように、それを行う1つの方法があります。もう 1 つは、自己実行型の無名関数を使用する方法です。

for( i = 0; i < $('.trigger').length; i++ ){
  (function(j) {
    $('.trigger:eq('+j+')').click(function(){
      $('.box:eq('+j+')').fadeIn();
    });

    $('.box:eq('+j+') .bt-close').click(function(){
      $('.box:eq('+j+')').fadeOut();
    });
  })(i);
}

ここでの違いは、外側の無名関数 (ループの内容をすぐにラップする関数) がループ変数にまったくアクセスしないため、ループ変数をキャプチャしないことです。代わりに、関数内で値が変更されないパラメーターで呼び出され、内部関数によってキャプチャされます。

ループ内で関数を作成してはいけないというわけではありません。ただし、そうする場合は、それらとループの間のループ変数をキャプチャするクロージャーが必要です。そのクロージャーを作成する関数が、@JoeTuskan の例のように外部で定義されているか、私のように内部で定義されているかは、スタイルの問題です。なぜそれが機能するのかを理解している限り。実際、彼の投稿で説明されている方法は、N 個の無名関数を作成し続けるため、この方法よりも少し速いはずですが、この方法で実際に何が起こっているのかを理解しやすいと思います。

于 2012-04-09T15:15:50.760 に答える
0

それぞれを使用してそれを行う別の方法:

var triggers = $('.trigger');
var boxes = $('.box');
triggers.each(
    function( ind ){
        var box = boxes.eq(ind);
        $(this).on("click", 
            function(){
                box.fadeIn();
            }
        );
    }
);

boxes.find(".bt-close").on("click", 
    function(){
        $(this).closest('.box').fadeOut(); //might be better to use parents(".box") - depends on HTML
    }
);
于 2012-04-09T15:27:50.613 に答える
0

この動作の背後にある理由は、それらfunction(){...}が閉鎖であるためです。つまり、クロージャーを作成すると、javascript インタープリターは関数宣言の時点で環境をコピーするため、関数がスコープ外であっても (クロージャーなしでガベージ コレクションされる場合でも) アクセスできます。

これの考えられる欠点の 1 つに直面しました: クロージャーはオブジェクトのコピーを受け取ら、変数にアクセスするだけです。例を考えてみましょう:

var i=0;
var closure = function() {alert(i);}
closure(); //alerts 0
i=1;
closure(); //alerts 1;

あなたの例でも同じことが起こります。ifor ループは最後まで実行され、値が残り$('.trigger').lengthます。

したがって、あなたが望むものを達成する適切な方法は、ジョー・タスカンの答えです

于 2012-04-09T15:20:16.780 に答える