0

変数を 2 つの異なるフィールド ID に変更する小さなスクリプトを作成しました。

var locationSelect = '#shipping_country_code';

function shippingColumn() {
    $(locationSelect).change(function(){
        var location = $(this).val();
        $('.shipping_country_code').val(location);
    });
}
shippingColumn();

$('#order_shipping_same_as_billing').change(function() {
    var checked = $(this).is(':checked');
    if (checked) {
        locationSelect = '#country_code';
    } else {
        locationSelect = '#shipping_country_code';
    }   
    shippingColumn();
});

コードは機能しますが、問題が 1 つあります。この変数はデフォルトで #shipping_country_code に設定されています。チェックボックスが変更されると、変数は #country_code に変更されます。ここまでは順調ですね。次に、チェックボックスを再度変更すると、何らかの理由で両方のフィールドが変数 locationSelect の変更時にトリガーされます。

私のコードでこれが起こる理由を誰でも見ることができますか?

4

1 に答える 1

3

変更リスナーを要素にバインドしています。実行パスのさらに下でどの変数を変更しても、そのリスナーは引き続きバインドされます。リスナーのバインドを解除するか、jQuery の を使用してバインドする必要があります.one

更新します。私.oneはあなたが必要としているものではないことを理解しています。リスナーをイベントにバインドします。このイベントは一度だけ発生し、その後登録を解除します。何度も発火し、状態に応じて登録を解除する可能性のあるものが必要です。イベントの登録を解除できるようにするには、参照がまったく同じ関数 (同一の関数だけでなく) であることが重要です。そのため、イベント ハンドラーをインラインで定義することはできません。

イベントの登録を解除する例は、次のようになります。

function selectChange() {
    var location = $(this).val();
    $('.shipping_country_code').val(location);
}

function shippingColumn() {
    $('#shipping_country_code, #country_code').unbind('change', selectChange);
    $(locationSelect).bind('change', selectChange);
}

デモ(わかりやすくするためにアクティブなクラスを追加しました)。

今。リスナーをバインドおよびバインド解除するときに、簡単に迷子になります。(通常) 絶対に避けたいことは、誤って同じリスナーを 2 回登録することです。別のアプローチをお勧めします。これは、イベントハンドラーを一度だけバインドし、両方のDOMReady要素に対して常に起動し、変更リスナーを使用して状態を確認するという問題が少なくなると思います。変数を調べて、イベントを処理する必要があるかどうかを確認します。

$('#shipping_country_code, #country_code').change(function() {
    if(!$(this).is(locationSelect)) return;
    var location = $(this).val();
    $('.shipping_country_code').val(location);
});

デモ

ユースケースでは、このソリューションで状態変数を実際に使用する必要がないことに注意してください。現在のイベントを発生時に処理する必要があるかどうかを評価するのは、ほぼ同じくらい簡単です。

$('#shipping_country_code, #country_code').change(function() {
    var sameAsBilling = $('#order_shipping_same_as_billing').is(':checked');
    if((this.id == 'country_code' && !sameAsBilling) ||
       (this.id == 'shipping_country_code' && sameAsBilling)) return;
    var location = $(this).val();
    $('.shipping_country_code').val(location);
});

デモ

リスナー内のロジックは少し複雑になりますが、すべてのロジックが 1 つのリスナーに含まれているため、大規模なプロジェクトではコード全体の複雑さが軽減される可能性があります。

于 2013-06-19T13:58:38.467 に答える