4

ko.computed()のようなコレクションをプロキシする関数があります。

function ListView(query) {
    var self = this;

    this.query = query;
    this.items = ko.observableArray([]);
    ko.computed( function() {
        self.items( self.query() == null ? [] : self.query().postings() );
    }

    // more code
}

残念ながら、これにより、self.items()postings() 配列内のすべてのオブジェクトが変更されるたびに、変数が変更されます。私がやりたいことは、計算された値のアイテムがクエリの投稿を直接表すようにすることです。しかし、私がこれを行うと:

 self.items = ko.computed(function() { return self.query().postings(); });

Knockout に関する限り、値は配列ではなくスカラーになります。これが重要な理由は、リスト内の一部のアイテムの状態が変化したときに、リスト全体を再レンダリングするのではなく、表示のそれらの部分だけを更新したいからです。これは単なるパフォーマンスの最適化ではありません (ただし、数百のアイテムではパフォーマンスも問題になります)、現在表示されているアイテムをログに記録して、ユーザーが見た可能性のあるものを追跡しようとしています。

論理的には、次のようなものが欲しいと思います。

  self.items = self.query().postings;

しかし、依存関係が別のオブジェクトに存在するため(私は思う)、クエリが変更されるとこれは壊れます。

依存メカニズムを構築し、コレクションのセマンティクスを保持するクリーンな方法はありますか?

編集日: 2012 年 5 月 13 日

@MichaelBest によって提案された拡張アプローチを実装しようとしましたが、次のエラーが発生しました。

Uncaught TypeError: Object function dependentObservable() {
        if (arguments.length > 0) {
            set.apply(dependentObservable, arguments);
        } else {
            return get();
        }
    } has no method 'valueWillMutate'
ko.utils.arrayForEach.ko.observableArray.fn.(anonymous function)    knockout-2.1.0.debug.js:1087
SubviewModel.self.refresh.self.doSort    SummaryViewModel.js:73
ko.ignoreDependencies    knockout-deferred-updates.js:172
subFnObj.(anonymous function).newCallback    knockout-deferred-updates.js:188
ko.subscribable.fn.notifySubscribers    knockout-2.1.0.debug.js:870
ko.utils.arrayForEach    knockout-2.1.0.debug.js:85
ko.subscribable.fn.notifySubscribers    knockout-2.1.0.debug.js:866
evaluateImmediate    knockout-deferred-updates.js:300
evaluatePossiblyAsync    knockout-deferred-updates.js:246
ko.subscribable.fn.notifySubscribers    knockout-2.1.0.debug.js:870
ko.utils.arrayForEach    knockout-2.1.0.debug.js:85
ko.subscribable.fn.notifySubscribers    knockout-2.1.0.debug.js:866
ko.observable.observable.valueHasMutated    knockout-2.1.0.debug.js:946
observable    knockout-2.1.0.debug.js:934
updateViewModel    knockout.mapping-latest.debug.js:514
changes    knockout.mapping-latest.debug.js:389
visitPropertiesOrArrayEntries    knockout.mapping-latest.debug.js:569
updateViewModel    knockout.mapping-latest.debug.js:374
ko.mapping.fromJS    knockout.mapping-latest.debug.js:91
Topic.load    querium.js:1212
...
4

2 に答える 2

3

配列を返し、次のように動作する計算されたオブザーバブルを作成できますobservableArray

self.items = ko.computed({
    read: function() { return self.query().postings(); }
    write: function(value) { self.query().postings(value); }
});
ko.utils.extend(self.items, ko.observableArray.fn);

observableArrayが持つすべての機能を で使用できるようになりましたitems

編集: このアプローチは、オブジェクトに関数valueWillMutateと関数も追加する場合にのみ機能します。valueHasMutated

self.items.valueWillMutate = function () { self.query().postings.valueWillMutate(); }
self.items.valueHasMutated = function () { self.query().postings.valueHasMutated(); }

また、これはKnockoutのデバッグバージョンを使用する場合にのみ機能します。これは、縮小バージョンでは関数名が圧縮されるためです。

于 2012-05-13T05:50:55.473 に答える
0

computedオブザーバブルを返すことができます:

self.items = ko.computed(function() { return self.query().postings; });

observableArray次に、次のようにプロキシを使用できます。

self.items().push(...);

基になる配列にアクセスするには、両方のオブザーバブルをアンラップする必要があります。

var postingsArray = self.items()();

于 2012-04-28T01:29:09.873 に答える