ViewModel の内部

ViewModel の機能を確認したので、次に内部で何が行われているか詳しく見てみましょう。メカニクスを基本的に理解していると、ViewModel が宣言に対して何を行うか分かるため、問題の診断に役立ちます。

ViewModel にはデータオブジェクトに対する変更の管理とデータ変更時のバインディングのスケジューリングの2つの明確な役割があります。

ViewModel データと継承

ViewModel クラスは “data” オブジェクトを管理し、JavaScript プロトタイプチェーンを利用して値の継承を提供します。参考図:

これは、すべてのコンポーネントが(データオブジェクト “Data 1” にストアされた)最上位コンテナで設定されるプロパティを読み取ることができることを意味します。これが Container 1 にあるとします。

viewModel: {
    data: {
        foo: 42
    }
}

これによって、すべてのコンポーネントは {foo} にバインドできます。これはアプリケーションの多くのレベルで必要とされる重要なレコード(“currentUser” など)を追跡するために通常使用されます。実際、JavaScript プロトタイプチェーンを使用してデータを表示しているため、プロパティへの変更も共有する場合に ViewModel でオブジェクトを公開することが多くの場合に役立ちます。その理由としては、{foo} への双方向のバインドを考えてみてください。ただし、Container 2 の子です。

{
    xtype: 'textfield',
    bind: '{foo}'
}

テキストフィールドは Data 2 のプロトタイプチェーン経由で “42” を受け取るので、最終的に Data 1 からになります。ただし、このコンポーネントへの変更は Data 2 にストアされます。これは、これらのコンポーネントがその ViewModel とデータオブジェクトにバインドされ、バインドの双方向なため実際には ViewModel 2 で set を呼び出し、標準 JavaScript オブジェクトとして sets foo を Data 2 で呼び出します。この「フォーク」は、ビューによって分割される値を初期化するための便利な方法です。

その代わり、“live” プロパティを継承を介して共有するためには、オブジェクトをルートの ViewModel にストアする必要があります。

viewModel: {
    data: {
        stuff: {
            foo: 42
        }
    }
}

これで、双方向のバインドが “stuff” オブジェクトの “foo” プロパティを更新するようになります。

{
    xtype: 'textfield',
    bind: '{stuff.foo}'
}

スケジューリングと依存関係

データを高速にバインドするためには冗長または不必要な計算を避けることが重要です。これを管理するために、ViewModel がデータ間の依存関係を追跡します。すべてのバインドと数式が依存関係を発生させます。内部的に、ViewModel はこれらを同時に1方向に分類し、線形スケジュールを作成します。このスケジュールはデータが変更されると遅れて処理されます。

つまり、ViewModel で値を設定するか、レコードのフィールドを変更した場合、多数の再計算がすぐに行われることを心配する必要はありません。同様に、数式が7つの値に依存し、すべてを変更する必要がある場合、数式は1度だけ再計算されます。さらに、7つの数式が他の数式を使用する場合(7つの深いチェーン)でそれぞれが7つの他の値に依存する場合、49の値すべてを変更すると、各数式は1度だけ再計算されます。

これを実現するためには、これらの依存関係を ViewModel が認識し、非循環でなければなりません。依存関係グラフのサイクルはエラーとして報告されます。この不自然な例で簡単に分かります。

Ext.define('App.view.broken.BrokenModel', {
    extend: 'Ext.app.ViewModel',

    formulas: {
        bar: function (get) {
            return get('foo') / 2;
        },
        foo: function (get) {
            return get('bar') * 2;
        }
    }
});

実際には、これらのバグはあまり明確にはなっていない可能性が高いですが、“foo” と “bar” は相互に依存関係にあるため、これらの2つのメソッドを評価する上で、適切な回答を導き出す順序は特にありません。

数式の依存関係

数式が明示的なバインドを使用する場合、その依存関係は明らかです。数式が関数または get メソッドのみを提供する場合、ViewModel は関数のテキストをパースし、プロパティのリファレンスを探します。これは非常に便利で明示的なバインドで依存関係をリスト表示し忘れないようにしますが、このアプローチには制約があります。数式のパースに関する詳細は、Ext.app.bind.Formula を参照してください。

Last updated