Angular 2 绑定到计算 getter 给出调试错误
Angular 2 bind to computed getter gives debug erros
我正在使用 Angular 2 和 lodash。
我有一个关系模型,我有一个 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 MessagesDetailsComponent@60:8'
has changed after it was checked. Previous
这似乎是完全正确的,因为实际上每次调用时都会计算它。
无论如何,拥有 "computed" 这样的变量,我无法想象 Angular 2 变化检测如何检测到 relationsPerType 实际上已经发生变化。
比如将 getter 标记为不可变的东西??
我想更好的方法是:
a) 从开始
开始就将计算出的 getter 值存储在 属性 中
b) 使父对象不可变以便 Angular 不跟踪属性的变化
有更好的方法吗?
您应该缓存该值并改为绑定到缓存的值,或者创建一个在数据更改时发出新事件的可观察对象。
如果绑定到 {{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>
经过一番挖掘,我找到了一种使用 装饰器 的更好方法,而不是 a) 和 b) 必须提供的方法,如:
a) 我不想放弃 getter 函数提供的 "lazy" 计算并使所有内容成为 属性
b) 不可变是一个可行的解决方案,但不适用于我的情况
所以,来自 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 装饰器装饰 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 依赖注入不要抱怨。此外,我没有松开 "lazy" 评估,也没有添加更改架构的辅助属性。
如果缓存变得陈旧,他当然必须处理他想要使缓存无效的情况。那将需要删除
`__cachedsetted${key}`
属性 从此.
我正在使用 Angular 2 和 lodash。
我有一个关系模型,我有一个 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 MessagesDetailsComponent@60:8' has changed after it was checked. Previous
这似乎是完全正确的,因为实际上每次调用时都会计算它。
无论如何,拥有 "computed" 这样的变量,我无法想象 Angular 2 变化检测如何检测到 relationsPerType 实际上已经发生变化。 比如将 getter 标记为不可变的东西??
我想更好的方法是:
a) 从开始
开始就将计算出的 getter 值存储在 属性 中b) 使父对象不可变以便 Angular 不跟踪属性的变化
有更好的方法吗?
您应该缓存该值并改为绑定到缓存的值,或者创建一个在数据更改时发出新事件的可观察对象。
如果绑定到 {{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>
经过一番挖掘,我找到了一种使用 装饰器 的更好方法,而不是 a) 和 b) 必须提供的方法,如:
a) 我不想放弃 getter 函数提供的 "lazy" 计算并使所有内容成为 属性
b) 不可变是一个可行的解决方案,但不适用于我的情况
所以,来自 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 装饰器装饰 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 依赖注入不要抱怨。此外,我没有松开 "lazy" 评估,也没有添加更改架构的辅助属性。
如果缓存变得陈旧,他当然必须处理他想要使缓存无效的情况。那将需要删除
`__cachedsetted${key}`
属性 从此.