Angular 2绑定到计算的getter提供调试错误

时间:2016-04-20 07:35:16

标签: javascript typescript angular decorator lodash

我正在使用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不跟踪属性的变化

有更好的方法吗?

2 个答案:

答案 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>