typescript Angular2 方法绑定错误:“检查后值已更改”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35710895/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 03:19:16  来源:igfitidea点击:

Angular2 method binding error: "value has changed after it was checked"

angularjsdata-bindingtypescriptangular

提问by Claudiu

I am trying to make a circle board in Angular2. For the example I want to make 10 circles but in reality this number can change. I want to calculate the radius of each circle, so it would be dynamic and not static. See the picture for exampleenter image description here

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

This is my code

这是我的代码

@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;
    }
}

But I get the following error:

但我收到以下错误:

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]

Is there maybe a better way of writing this for loop with *ngForinstead of writing this in a separate method?

是否有更好的方法来编写 for 循环*ngFor而不是在单独的方法中编写它?

回答by Mark Rajcok

In development mode (the default), change detection is run twiceto ensure that model changes have stabilized. This means that the ngForloop is evaluated twice. Hence property xwill continue to be decremented the second time change detection runs. Other activity in your app will also cause change detection to run, and xwill continue to be decremented. Therefore, you must write all view functions, like calculateRadius(), assuming they will be executed many times. E.g.:

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

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

The Template Syntax dev guide mentions this when it describes idempotent expressions.

模板语法开发指南在描述幂等表达式时提到了这一点。

This will also solve the value has changed after it was checkedproblem.

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

You also need to bind SVG attribute rusing this syntax: [attr.r]="...", not [style.r]="...".

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

Plunker

Plunker

回答by basarat

“value has changed after it was checked”

“检查后值已更改”

The return from any valuemust be deterministic. Means if I call value(might be calculateRadius()) with the sameinputs it should give the sameoutput.

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

So pass indexinto calculateRadius(or whatever valueis giving that error)

因此,通过index进入calculateRadius(或任何value被赋予的错误)