4

javascript (jQuery を使用) を使用して順序付けられていないリストを生成しています。各リストアイテムは、「クリック」イベント用の独自のイベント リスナーを受け取る必要があります。しかし、正しいコールバックを正しいアイテムにアタッチするのに問題があります。(削除された) コード サンプルを使用すると、問題が少し解決する可能性があります。

for(class_id in classes) {
    callback = function() { this.selectClass(class_id) };
    li_item = jQuery('<li></li>')
                .click(callback);
}

実際、このイテレーションではさらに多くのことが行われていますが、質問とはあまり関係がないと思いました。いずれにせよ、何が起こっているかというと、コールバック関数が保存(& コピー)ではなく参照されているように見えます。最終結果?ユーザーがリスト項目のいずれかをクリックすると、その特定のポイントに格納されている関数を使用するため、常に配列の最後のアクションが実行されます。 class_idclassescallback

href汚い回避策 (囲まれた要素内の属性を解析するなど) を見つけましaたが、「クリーンな」方法で目標を達成する方法があるかどうか疑問に思っていました。私のアプローチが恐ろしい場合は、その理由を教えてください :-) ありがとう!

4

6 に答える 6

8

これは古典的な「閉鎖が必要」の問題です。これが通常のプレイ方法です。

  1. いくつかの値を反復する
  2. 反復変数を使用するその反復で関数を定義/割り当てます
  3. すべての関数が最後の反復からの値のみを使用することがわかります。
  4. なんてこと?

繰り返しますが、このパターンを見ると、すぐに「閉鎖」と考えるはずです。

例を拡張すると、クロージャーを入れる方法は次のとおりです

for ( class_id in classes )
{
  callback = function( cid )
  {
    return function()
    {
      $(this).selectClass( cid );
    }
  }( class_id );
  li_item = jQuery('<li></li>').click(callback);
}

ただし、jQuery のこの特定のインスタンスでは、クロージャーは必要ありませんが、変数の性質について尋ねなければなりませんclasses。それはオブジェクトですか? オブジェクトを示唆する for-in ループを反復処理するためです。そして、私にとっては、なぜこれを配列に格納しないのですか? もしそうなら、あなたのコードはこれだけかもしれません。

jQuery('<li></li>').click(function()
{
  $(this).addClass( classes.join( ' ' ) );
});
于 2009-07-09T14:59:51.187 に答える
2

これは、あなたが望むことを行うためのよりクリーンな方法です。

.data() を使用して要素に class_id 情報を追加します。

次に、.live() を使用してすべての新しい要素にクリック ハンドラーを追加します。これにより、x * クリック関数が回避されます。

for(class_id in classes) {
    li_item = jQuery('<li></li>').data('class_id', class_id).addClass('someClass');
}

//setup click handler on new li's
$('li.someClass').live('click', myFunction )

function myFunction(){
   //get class_id
   var classId = $(this).data('class_id');
   //do something
}
于 2009-07-09T15:03:27.123 に答える
1

私のjavascript fuはかなり弱いですが、私が理解しているように、クロージャーはスタック上のローカル変数を参照します(そして、そのスタックフレームは関数とともに渡されますが、これも非常に大ざっぱです)。各関数が同じ変数への参照を保持しているため、あなたの例は実際には機能しません。代わりに、クロージャーを作成する別の関数を作成してみてください。

function createClosure(class_id) {
  callback = function() { this.selectClass(class_id) };
  return callback;
}

その後:

for(class_id in classes) {
  callback = createClosure(class_id);
  li_item = jQuery('<li></li>').click(callback);
}

もちろん、それは少し面倒です。おそらくもっと良い方法があります。

于 2009-07-09T14:58:45.603 に答える
1

それらをすべて生成してから、次のようなものを呼び出すことができないのはなぜですか

$(".li_class").click(function(){ this.whatever() };

編集:

さらにクラスを追加する必要がある場合は、ループ内にすべてのクラス名を含む文字列を作成し、それをセレクターとして使用します。

$(".li_class1, .li_class2, etc").click(function(){ this.whatever() };
于 2009-07-09T14:46:58.700 に答える