2012-04-22 60 views
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()變量與每一個變化中的貼子的每個對象()數組來改變。我寧願做的是有一個計算的值項目直接代表查詢的發佈。但是,如果我這樣做:

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 
... 

回答

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); 

現在你可以使用所有的f observableArrayitems有聯繫。

編輯:這種做法只會工作,如果您還添加valueWillMutatevalueHasMutated函數對象:

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

,這也只會工作,如果你使用調試版本的基因敲除,因爲在縮小版本版本,函數名稱將被壓縮。

+0

我在使用這種方法傳播更新時遇到了問題。查看帖子以瞭解堆棧跟蹤。 – 2012-05-13 22:30:39

+0

沒錯。對不起,我錯過了。 – 2012-05-14 02:52:29

+0

self.query()可能返回null的事實給了我一些麻煩,但我想我最終得到了這個工作。 – 2012-05-14 06:50:31

0

你可以有computed返回一個可觀察到的:

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

然後你就可以使用代理observableArray這樣的:

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

訪問底層數組,你必須解開這兩個觀測:

var postingsArray = self.items()();

+0

我打算試一試......但它肯定會讓代碼更難理解。能夠以聲明方式指定計算值的語義會很好。 – 2012-05-12 16:33:35