0

KnockoutJS を使用したページがあり、オブザーバブルの数がやや多くなっています (ここでは約 35 個、合計で約 60 個)。KO マッピング プラグインを使用していますが、それが問題に関係しているかどうかはわかりません。

オブザーバブルのほとんど (すべてではない) は、入力フィールドにバインドされています。

ユーザーは、現在の入力セットを名前付きセットに保存するか、以前に保存したセットから再読み込みできます。現在の入力セットが保存されたセットからのものか、編集された (保存されていない) 入力かを示す UI があります。

入力のいずれかが編集されたときに「保存/読み込み入力」UI を更新するために (どれを気にする必要はありません)、関連するすべての「入力」オブザーバブルをサブスクライブします。

これが私の奇妙な問題です。サブスクライブされたオブザーバブルの数が約 25 以上になると、呼び出しの奥深くからコールバック関数への偽の呼び出しが行われko.applyBindings(...)ます。

  • それが発生すると、スプリアス コールバックは 1 つだけです。
  • 報告される入力は、通常、私が最後に購読したものです。
  • 約 25 以下にサブスクライブするのに十分な数のサブスクリプションを削除すると、偽のコールバックは表示されなくなります。
  • その制限を超えてサブスクリプションを追加し続けると、リストに追加し続けると、さまざまなフィールドに対して呼び出しが再表示されます。
  • __ko_mapping__すべての入力を購読すると、コールバックはばかげたコールバックであると主張します。

サブスクリプションに正しくバインドしていないか、KO または KO マッピング プラグインにバグがあり、サブスクリプションのリストがめちゃくちゃになっていると想定する必要があります。これまで問題を追跡できませんでした。

サブスクリプション コードは、おおよそ次のようになります。

// markSavedInputsDirty(name) defined elsewhere
function registerCallbacks() {
    var data = viewModel.inputs;
    var member;
    for(member in data) {
        if (data.hasOwnProperty(member) && ko.isObservable(data[member])) {
            if(member /* ... not certain observables which I need to ignore */ ) {
                data[member].subscribe(function() {return markSavedInputsDirty(member)}, data[member]);
            }
        }
    }
}

(注: 上記のコードは、どのメンバーが呼び出されているかを追跡しますが、デバッグ支援としてのみです。最初に問題が発生したのを見たとき、コードはすべてのオブザーバブルに対して同じコールバック関数 (カリー化なし) を使用していました)

誰もこのようなものを見たことがありますか?

4

1 に答える 1

0

解像度:

subscribe(...)@MichaelBestがコメントで示したように、通話の閉鎖はめちゃくちゃでした。member呼び出しの時点での値が含まれていると思いましたが、それmember自体 (すべての呼び出しで同じオブジェクト) が含まれています。私が見ていたのmemberはループからの最終的な値であり、それが私を迷わせていました。真夜中にやるべきではなかった。

その行の正しい実装は次のとおりです。

data[member].subscribe(markSavedInputsDirty.bind(data[member], member));

適切な診断を行うと、すべてが明らかになりました。偽の呼び出しは、ページ内の要素のvalueバインディングから発生しています。Knockout は、選択された の値が の値と正確に同じである<select>ことを内部的に確認する必要があります ( Knockout のソースを参照)。<option>viewModelensureDropdownSelectionIsConsistentWithModelValue(...)

私の場合、観察可能な値には 3 (数値) があり、選択された<option>- 当然のことながら - "3" (文字列) がありました。したがって、Knockout は viewModel をオプションの値に設定し、それが通知をトリガーしました。

したがって、元のサブスクリプション (カリー化の試みが失敗する前) は正しく、通知は正当なものでした。バインド後まで監視コードが影響を与えないように、物事を入れ替える必要があるだけです。

于 2012-09-25T12:52:56.830 に答える