0

neutral、、の3つの異なるクラスを取得する要素がたくさんありmarkedVますmarkedX。ユーザーがこれらの要素の1つをクリックすると、クラスは1回切り替わります:ニュートラル->マークV->マークX->ニュートラル。クリックするたびにクラスが切り替わり、関数が実行されます。

$(document).ready(function(){
  $(".neutral").click(function markV(event) {
    alert("Good!");
    $(this).addClass("markedV").removeClass("neutral");
    $(this).unbind("click");
    $(this).click(markX(event));
  });
  $(".markedV").click(function markX(event) {
    alert("Bad!");
    $(this).addClass("markedX").removeClass("markedV");
    $(this).unbind("click");
    $(this).click(neutral(event));
  });
  $(".markedX").click(function neutral(event) {
    alert("Ok!");
    $(this).addClass("neutral").removeClass("markedX");
    $(this).unbind("click");
    $(this).click(markV(event));
  });
});

しかし、明らかにこれは機能しません。私には3つの障害があると思います。

  1. 変更する要素を、実際に定義される前に、すでに定義されている関数に適切にバインドするにはどうすればよいですか?

  2. 新しくバインドされた関数にイベントを確実に渡す方法[markX(event)のように'event'を関数に送信しても達成されないと思います]

  3. 全体が繰り返しに見えますが、変更されるのはアラートアクションだけです(各関数の動作は異なりますが、必ずしもアラートである必要はありません)。これに対するよりエレガントな解決策はありますか?

4

3 に答える 3

1

イベントハンドラーを常にバインドおよびバインド解除する必要はありません。

これらすべてのオプションに対して1つのハンドラーが必要です。

$(document).ready(function() {

    var classes = ['neutral', 'markedV', 'markedX'],
        methods = {
            neutral: function (e) { alert('Good!') },
            markedV: function (e) { alert('Bad!') },
            markedX: function (e) { alert('Ok!') },
        };

    $( '.' + classes.join(',.') ).click(function (e) {
        var $this = $(this);

        $.each(classes, function (i, v) {
            if ( $this.hasClass(v) ) {
                methods[v].call(this, e);
                $this.removeClass(v).addClass( classes[i + 1] || classes[0] );
                return false;
            }
        });
    });
});

これがフィドルです:http://jsfiddle.net/m3CyX/

于 2013-01-15T03:03:56.980 に答える
1

このような場合は、イベントを上位の親にアタッチし、イベントを委任する必要があります。

イベントはクラスではなく要素に関連付けられていることに注意してください。

このアプローチを試してください

$(document).ready(function () {
  $(document).on('click', function (e) {
    var $target = e.target;
    if ($target.hasClass('markedV')) {
      alert("Good!");
      $target.addClass("markedV").removeClass("neutral");
    } else if ($target.hasClass('markedV')) {
      alert("Bad!");
      $target.addClass("markedX").removeClass("markedV");
    } else if ($target.hasClass('markedX')) {
      alert("Ok!");
      $target.addClass("neutral").removeClass("markedX");
    }
  });
});

または @Bergiが提案したように

$(document).ready(function () {
  $(document).on('click', 'markedV',function (e) {
    alert("Good!");
    $(this).addClass("markedV").removeClass("neutral");
  });
  $(document).on('click', 'markedX',function (e) {
    alert("Bad!");
    $(this).addClass("markedX").removeClass("markedV");
  });
  $(document).on('click', 'neutral',function (e) {
    alert("Ok!");
    $(this).addClass("neutral").removeClass("markedX");
  });
});

ここで、ドキュメントは任意の静的な親コンテナに置き換えることができます。

于 2013-01-15T03:06:06.003 に答える
0

変更する要素を、実際に定義される前に、すでに定義されている関数に適切にバインドするにはどうすればよいですか?

要素を関数にバインドするのではなく、ハンドラー関数を要素のイベントにバインドします。定義される前に関数を使用することはできません(ただし、宣言されたコード内の場所より上の関数を使用する場合があります-「ホイスト」と呼ばれます)。

新しくバインドされた関数にイベントを確実に渡す方法[markX(event)のように'event'を関数に送信しても達成されないと思います]

これは、ハンドラーが呼び出されたときに暗黙的に発生することです。関数を渡すだけで済みます-呼び出さないでください!ただし、問題は、名前付き関数の式に外部からアクセスできないことです。

全体が繰り返しに見えますが、変更されるのはアラートアクションだけです(各関数の動作は異なりますが、必ずしもアラートである必要はありません)。これに対するよりエレガントな解決策はありますか?

はい。ハンドラーを1つだけ使用し、現在の状態で何をするかを動的に決定します。ハンドラーを着実にバインドおよびバインド解除しないでください。または、イベント委任を使用します。

于 2013-01-15T03:07:03.800 に答える