0

私は、計算された値に対する書き込み関数が、少なくともそれ自体でミューテーションイベントを自動的に発生させない理由を特定しようとしてきました。

私が話していることの例:

<span data-bind="text: fullName"></span>
<input data-bind="value: fullName"/>

次のJavaScriptを使用します。

<script type="text/javascript">
function MyViewModel() {
    this.firstName = 'first';
    this.lastName = 'last';

    this.fullName = ko.computed({
        read: function () {
            return this.firstName + " " + this.lastName;
        },
        write: function (value) {
            var lastSpacePos = value.lastIndexOf(" ");
            if (lastSpacePos > 0) { // Ignore values with no space character
                this.firstName = value.substring(0, lastSpacePos); // Update "firstName"
                this.lastName = value.substring(lastSpacePos + 1); // Update "lastName"
            }
        },
        owner: this
    });
}

ko.applyBindings(new MyViewModel());

firstNameとlastNameは監視可能ではないため、これが発生することは理解していますが、その理由はわかりません。基になるデータが他の場所で個別に使用されていたとしても、少なくともfullNameを使用するすべてのフィールドが更新されることは論理的に思われます。

だから私の質問は具体的には:

  1. なぜこうなった?
  2. firstNameまたはlastNameを監視したくない場合、どうすれば回避できますか?

http://jsfiddle.net/TWR6Y/

4

1 に答える 1

4

これは、依存関係の追跡がどのように機能するかと関係があります。

  1. 計算されたオブザーバブルを宣言するたびに、KOはすぐにそのエバリュエーター関数を呼び出して初期値を取得します。
  2. エバリュエーター関数の実行中、KOは、エバリュエーターが値を読み取るオブザーバブル(または計算されたオブザーバブル)のログを保持します。
  3. 評価者が終了すると、KOは、タッチした各オブザーバブル(または計算されたオブザーバブル)へのサブスクリプションを設定します。サブスクリプションコールバックは、エバリュエーターを再度実行するように設定されており、プロセス全体をステップ1にループバックします(適用されなくなった古いサブスクリプションを破棄します)。
  4. KOは、計算されたオブザーバブルの新しい値についてサブスクライバーに通知します。

firstNameとはそうでlastNameはないのでko.observable、KOはそれらをログに追加しません(ステップ2を参照)。そのため、(オブザーバブルなしの)コードは機能しません。

答えをさらに要約します。この質問と更新の時点でのJavascriptは、ネイティブ型のイベント処理を提供できません。Knockoutは、オブジェクトへの変異を確認できるインターセプトポイントを作成するようにデータを処理することにより、この問題を克服します。傍受せずにネイティブを観察する唯一のアプローチは、非効率的なスキャンです。

この問題は、Object.observeによって解決されます。

于 2013-02-23T19:38:33.430 に答える