4

サブスクライブ関数内でオブザーバブルの値を変更するにはどうすればよいですか? 例えば

JS モデル:

function Model(){
    self = this;
    self.Test = ko.observable(2);
    self.Test.subscribe(function (){
      if (/**Some bool expression**/) {
         self.Test(2);
      }
    });
}

HTML:

<input type="radio" value="1" data-bind="checked:Test" />
<input type="radio" value="2" data-bind="checked:Test" />
<input type="radio" value="3" data-bind="checked:Test" />

デフォルトでは、2 番目の無線入力がチェックされています。最初のラジオをクリックすると、最初と 2 番目の両方が選択されます。

ここに画像の説明を入力

更新: jQuery とノックアウトの両方を含めると発生します。jquery を削除すると、すべて問題ありません。しかし、それは単なるテストページです。実際のプロジェクトでは、いくつかの場所で jQuery を使用する必要があり、この場合は削除できません。

サンプル。テスト ページのソース:

<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <script type="text/javascript" src="knockout-2.1.0.js"></script>
        <script type="text/javascript" src="jquery-1.6.4.js"></script>
        <script type="text/javascript">
            function Model(){
                self = this;
                self.Test = ko.observable(2);
                self.Test.subscribe(function (){
                  if (true) {
                     self.Test(2);
                  }
                });
            }
        </script>
    </head>
<body>
    <input type="radio" value="1" data-bind="checked:Test" />
    <input type="radio" value="2" data-bind="checked:Test" />
    <input type="radio" value="3" data-bind="checked:Test" />
</body>
<script type='text/javascript'>
    ko.applyBindings(new Model());
</script>
</html>
4

2 に答える 2

7

更新 (2015-02-27): Knockout 3.1.0 の時点で、Knockout にはイベントの「回避策」コードが含まれておらずclick、質問の例を問題なく処理できるはずです。http://jsfiddle.net/9S96U/3/


jQuery が含まれている場合、Knockout はそれを使用して、clickラジオ ボタンへの応答に使用されるイベントなどのイベントを処理します。クリック ハンドラーがラジオ ボタンの正しいチェック状態を認識できるようにするための「回避策」コードが含まれていますが、これは途中でチェック値をリセットしようとするコードに干渉するようです。

解決策は、setTimeout を使用して値を更新することです。これにより、クリック ハンドラーが終了した後に発生します。

function Model(){
    var self = this;
    self.Test = ko.observable(2);
    self.Test.subscribe(function (){
        setTimeout(function() {
            self.Test(2);
        });
    });
}

例: http://jsfiddle.net/9S96U/1/

また、上書きしないようにvarbeforeを含める必要self = thisがありますwindow.self

于 2012-10-24T22:41:53.320 に答える
0

サブスクライブ/パブリッシングの背後にある考え方は、1 人のオブザーバーが、独自のテストを行う複数のサブスクライバーに結果を送信できるようにすることです。

私は実際にはまだ knockout.js を使用していませんが、委譲/非同期フロー/プロミスなどで多くの作業を行ってきました。ほとんどの場合、特別な場合に軽量のカスタム実装を使用しています。

あなたの目標は、テストを 1 回実行するコントローラー (現在取得しているもの) を用意し、それぞれを反復処理して、正しいもの ( i - 1) がチェックされ、他のすべてがチェックされていないことを確認することです...

...または、より伝統的なパブリッシャー/サブスクライバーのやり方で、1 つのパブリッシャー (fieldsetすべてのラジオ コントロールの親要素である可能性のある のように) が、入力の 1 つが変更されるのをリッスンし、サブスクライブのそれぞれに通知する値を入力し、独自のテストを実行させます。

擬似的に言えば:

var subscribers = []; // array of input "Model" callbacks
                      // (ie: tests to determine whether they're off or on)

parentElement.listen("click", function (e) {
        var self = this,
            selectedRadio = e.target,
            val = selectedRadio.value;

        subscribers.forEach(function (notify) { notify(val); });
});

現在の状況を処理するには、依存性注入を使用できます。

new Model( value );

また

new Model( subscription_test_for_element );

予想されるテスト値をキャッシュする場所、または個々のインスタンス内の入力固有のテスト/成功/失敗ロジックをキャッシュする場所...

...または、各入力のハードコードされたロジックを処理するためのより大きなコントローラー (推奨されません) を作成します。

もちろん、モデル何であるか、インスタンス化の方法、ジェネリック モデルになる場合にサブスクリプションを構造にハードコーディングする理由などに基づいて、より具体的なヘルプを提供できます。

于 2012-10-24T21:01:24.113 に答える