2013-07-16 56 views
1

我有一個viewmodel是由構造函數創建的,有一些可觀察的屬性和一堆普通的舊屬性。一旦我實例化它,如果我在實例上設置了一個值,那麼對該值的更改不會反映在計算的observable中。Knockout:構造函數中的計算Observable忽略實例變化

這裏的精華版本就是我要找的:

function ViewModel(active) { 
    var self = this; 
    self.active = active; 

    self.getClasses = ko.computed(function() { 
     return this.active ? "yup" : "nope"; 
    }, self); 
} 

var vm = new ViewModel(false); 
vm.active = true; 

alert(vm.getClasses()); //returns "nope" :/ 

此計算觀察到的,如果我觸摸可觀察到的這取決於,但稱這是直接導致評估與舊值將重新評估活躍的。

ko.computed是否會創建一個忽略父級更新的新閉包?將明顯的數值與可觀察的數值混合起來是否不恰當? (這個計算結果我實際上遇到了依賴關於observables和其他屬性的問題,但我不希望其他屬性在運行時發生變化。這實際上只是我單元測試中的一個問題。)

我當然可以活躍一個可觀察的,但我想知道是否有另一種方式來做到這一點。

+1

只有在計算的函數中可觀察屬性發生改變時,計算值纔會更改。如果沒有可觀察到的變化,那麼計算結果將不會被重新評估......所以你需要設置'self.active = ko.observable(active);'或者不要在這裏使用計算,而是使用一個常規函數:'self .getClasses = function(){ return self.active? 「yup」:「nope」; };'進一步閱讀:http://knockoutjs.com/documentation/computedObservables.html依賴關係跟蹤如何工作部分 – nemesv

+0

同樣,我知道使活動可觀察性將導致計算可觀察更新。問題是我希望它在我調用*時更新,而不是簡單地在依賴關係發生變化時更新。 –

+2

這不是'ko.computed'的工作原理。評估函數僅在內部調用,並且僅在依賴的可觀察值發生更改時調用。您無法告訴計算機更新其值。所以不要在這裏使用計算。 – nemesv

回答

3

Josh在內部ko.computed立即執行您的計算函數並存儲結果,直到某些操作需要它重新計算自身爲止(如訂閱的可觀察變化)。這種內部緩存可能提供巨大的性能提升;如果由於結果應該相同而沒有訂閱值發生變化,則無需重新運行計算。

這就是爲什麼重要的是你的計算所依賴的任何值都被創建爲可觀察值。

目前沒有辦法強制計算重新計算需求,因爲通常這會表明您的架構存在問題。如果您需要按需計算的值,但不依賴於任何可觀察值,那麼常規函數將是實現這一點的最佳方式。

self.getClasses = function() { 
     return self.active() ? "yup" : "nope"; 
    }; 

可以綁定你的用戶界面,顯示的常規功能一樣的作爲對計算出的結果,但你需要在你的綁定表達式添加括號。請記住,這隻會在綁定時顯示該函數的結果。如果您的計算更改,UI將不會保持最新;因爲你需要一個ko.computed。

<!-- this will only show the value at bind-time and never be updated --> 
<div data-bind="text: getClasses()"></div> 

正如你所看到的,這不是很有用。總體而言,還有一些可觀測數據可能不會影響您的應用程序性能超過幾微秒。我的建議是暫緩優化代碼,直到看到問題。您的用戶更有可能看到循環評估或大型AJAX有效載荷的速度減緩,而不是讓您的代碼更容易編寫的一些觀察值。

我希望這有助於!

0

如果您希望通知此變量的變化(並在計算中進行評估),則活動必須是可觀察的。

1

你有沒有嘗試設置觀察到的值是這樣的:

function ViewModel(active) { 
    var self = this; 

    self.active = ko.observable(active); 

    self.getClasses = ko.computed(function() { 
     return this.active() ? "yup" : "nope"; 
    }, self); 
} 

var vm = new ViewModel(false); 
vm.active(true); 

因此設置觀察到的函數(方括號之間的值),而不是像一個屬性。並確保active被定義爲可觀察。

相關問題