我正在使用Angular 2和lodash。
我有一个关系模型,我有一个像这样的吸气剂:
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>
给我以下错误:
MessagesDetailsComponent @ 60:8&#39;中的表达式&#39; Message.relationsPerType 检查后发生了变化。以前
这似乎是完全正确的,因为每次调用它时都会计算它。
在任何情况下,有&#34;计算&#34;这样的变量我无法想象Angular 2变化检测如何检测到RelationsPerType实际上已经改变了。 像将getter标记为不可变的东西?
我想更好的方法是:
a)将计算出的getter值存储在一个属性中,从开始
b)使父对象不可变,以便Angular不跟踪属性的变化
有更好的方法吗?
答案 0 :(得分:1)
经过一番挖掘后,我找到了一种更好的方法,使用装饰器,而不是a)和b)必须提供,如:
a)我不想放弃getter函数提供的“懒惰”计算并使所有属性成为属性
b)不可变是一种可行的解决方案,但不适用于我的案例
所以,来自C#和许多面向方面的编程(参见PostSharp),我终于设法创建了一个缓存属性getter decorator 函数,每个对象只评估一次:
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装饰器装饰getter,如下所示:
@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}`
属性。
答案 1 :(得分: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>