2016-04-20 15 views
1

我正在使用Angular 2和lodash。Angular 2綁定到計算得到的getter給出調試錯誤

我有關係的典範,我有這樣的一個getter:

get relationsPerType() { 
    return _(this.Relations) 
     .groupBy(p => p.Type) 
     .toPairs() 
     .map(p => ({ 
      type: <MessageRelationType>p[0], 
      relations: <Relation[]>p[1] 
     })); 
} 

relationsPerType的值綁定到一個* ngFor指令

編輯:這是我的綁定:

<div *ngFor="#relationGroup of Message.relationsPerType"> 
    ... 
</div> 

給我以下錯誤:

Expression 'Message.relationsPerType in [email protected]:8' has changed after it was checked. Previous

這似乎是完全正確的,因爲實際上每次調用它時都會計算這個值。

在任何情況下,具有這樣的「計算」變量我無法想象Angular 2如何改變檢測可以檢測到relationsPerType實際上已經改變。 就像把getter標記爲不可變?

我想一個更好的辦法是:

一)要存儲產權裏面計算的吸氣值從開始

b)根據父對象的不可變的,從而爲角不跟蹤更改on properties

有沒有更好的方法來做到這一點?

+0

你如何綁定? –

回答

1

一些挖後,我發現使用裝飾一個更好的辦法,比a)和b)所提供的,如:

a)我不想放棄吸氣功能提供的「懶惰」計算,並將所有東西都歸爲屬性

二)永恆是一個可行的解決方案,但以我的情況不適用

所以,從C#和大量的面向方面編程(見PostSharp)的到來,我終於成功地創建一個緩存屬性getter裝飾函數,評估每個對象只有一次:

function cachedProperty(target: any, key: string, descriptor: PropertyDescriptor) { 
    let originalGetter = descriptor.get; 
    descriptor.get = function() { 
     let cachSetted = this[`__cachedsetted${key}`]; 
     if (typeof cachSetted !== 'undefined') { 
      return this[`__cached${key}`]; 
     } 
     this[`__cachedsetted${key}`] = true; 

     return this[`__cached${key}`] = originalGetter.call(this); 
    } 
} 

後,所有需要改變的是裝飾與@cachedProperty裝飾,吸氣,像這樣:

@cachedProperty 
    get relationsPerType() { 
     return _(this.Relations) 
      .groupBy(p => p.Type) 
      .toPairs() 
      .map(p => ({ 
       type: <MessageRelationType>p[0], 
       relations: <Relation[]>p[1] 
      })).value(); 
    } 

使用這個裝飾器,對象只會改變一次,所以Angular 2依賴注入不會投訴。另外,我不會放鬆「懶惰」評估,並且我不添加幫助程序屬性來更改我的模式。

當然,他必須處理的情況下,他想要使緩存失效,如果這變得陳舊。這將需要刪除

`__cachedsetted${key}` 

屬性從此。

0

您應該緩存該值並將其綁定到緩存值,或者創建一個在數據更改時發出新事件的observable。

如果綁定到{{relationsPerType}}每次都會創建一個新的集合Angular檢查是否發生了變化,Angular將此視爲變化,因爲它獲取兩個不同的實例,即使它們可能包含相同的數據。

calcRelationsPerType() { 
    this relationsPerType = _(this.Relations) 
     .groupBy(p => p.Type) 
     .toPairs() 
     .map(p => ({ 
      type: <MessageRelationType>p[0], 
      relations: <Relation[]>p[1] 
     })); 
} 

那麼這樣的結合應該很好地工作:

<div *ngFor="#relationGroup of Message.relationsPerType"> 
    ... 
</div> 
+0

HeyGünter!我認爲你的第一個片段有一個錯字:'這relationsPerType = return _(this.Relations)';-) –

+0

謝謝Günter。你說的是真實的「a)將計算得到的getter值從start開始存儲到一個屬性中」,在綁定數據之前需要額外努力調用calcRelationsPerType()。 –

+0

很難判斷您在問題中提供的信息是否付出了很大的努力。您需要找到一種方法,以便在值更改結果依賴時重新計算它。最簡單易懂的解決方案是我在答案中展示的恕我直言。更高級的將使用observables。你的裝飾器方法也很有趣,但我認爲使緩存無效與調用重新計算非常相似。 –