【问题标题】:Angular2 method binding error: "value has changed after it was checked"Angular2方法绑定错误:“检查后值已更改”
【发布时间】:2016-06-13 03:52:52
【问题描述】:

我正在尝试在 Angular2 中制作圆板。例如,我想制作 10 个圆圈,但实际上这个数字可以改变。我想计算每个圆的半径,所以它是动态的而不是静态的。以图片为例

这是我的代码

@Component({
    selector:"circle"
    template: `
  <svg>
    <circle *ngFor='#item of forLength #i=index #l=last #e=even'
            cx="50%" cy="50%" [style.r]="calculateRadius()" stroke="black" stroke-width="5" fill="white"></circle>
  <svg/>  
    `
})

export class CircleComponent{
    public maxRadius:number=25;
    public totalRounds:number=10;
    public x:number=30;

    public calculateRadius():number{
        var distanceBetweenCircles=this.maxRadius/(this.totalRounds-1);
        this.x-= distanceBetweenCircles;
        return this.x;
    }
}

但我收到以下错误:

calculateRadius() in CircleComponent@7:30' has changed after it was checked. 
    Previous value: '-7.500000000000007'. 
    Current value: '-36.66666666666668' in [calculateRadius() in CircleComponent@7:30]

有没有更好的方法用*ngFor 编写这个for 循环,而不是用单独的方法编写这个?

【问题讨论】:

  • 您在模板中的哪里调用calculateRadius()?您在模板中的何处设置 SVG r 属性?
  • @MarkRajcok 对不起,我在代码中写了一个错误,我现在已经更新了代码。我在 标签 中使用 calculateRadius()

标签: angularjs data-binding typescript angular


【解决方案1】:

在开发模式下(默认),变更检测是run twice,以确保模型变更已经稳定。这意味着ngFor 循环被评估了两次。因此属性x 将在第二次更改检测运行时继续递减。您应用中的其他活动也将导致更改检测运行,并且x 将继续递减。因此,您必须编写所有视图函数,例如calculateRadius(),假设它们将被执行多次。例如:

public calculateRadius(i):number{
    return this.x - i*this.distanceBetweenCircles;
}

模板语法开发指南在描述 idempotent expressions 时提到了这一点。

这也将解决value has changed after it was checked 问题。

您还需要使用以下语法绑定 SVG 属性 r:[attr.r]="...",而不是 [style.r]="..."。

Plunker

【讨论】:

  • 谢谢!没有比这更好的解释了。现在可以了!
  • 从Angular2 RC3开始,可以通过改变检测策略来解决这种情况: import {ChangeDetectionStrategy} from '@angular/core'; @Component({changeDetection: ChangeDetectionStrategy.OnPush})
  • @BecarioSenior,我不建议使用 OnPush 作为解决此问题的方法。 OnPush 应该与仅依赖于其输入属性且此处没有输入属性的组件一起使用。即使我们要添加一个输入属性,组件方法也不应该以这种方式修改输入属性的值(在这种情况下,这样的输入属性应该是只读的,在我看来)。此外,模板中使用的表达式应该是幂等的。
【解决方案2】:

“检查后值发生了变化”

任何value 的返回必须是确定性的。意味着如果我用 same 输入调用value(可能是calculateRadius()),它应该给出 same 输出。

所以将index 传递给calculateRadius(或任何value 给出的错误)

【讨论】:

    猜你喜欢
    • 2017-12-01
    • 1970-01-01
    • 2016-04-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-08
    • 2017-06-26
    • 2017-08-28
    相关资源
    最近更新 更多