ngIf - 检查后表达式已更改

nao*_*omi 24 angular2-changedetection angular

我有一个简单的场景,但只是无法让它工作!

在我看来,我在一个高度有限的盒子里显示一些文字.

正在从服务器获取文本,因此视图会在文本进入时更新.

现在我有一个"扩大"按钮,有一个ngIf显示的按钮,如果在框中的文本溢出.

问题在于,因为文本在获取时会发生变化,所以"扩展"按钮的条件会true在Angular的变化检测结束后变为...

所以我得到了这个错误:表达式在检查后发生了变化.上一个值:'false'.当前值:'true'.

显然按钮没有显示......

看到这个Plunker(检查控制台以查看错误...)

知道如何使这项工作?

Tie*_*han 40

发生此错误,因为您在dev mode:

dev mode更改检测中,在每次常规更改检测运行后添加一个额外的转弯,以检查模型是否已更改.

所以,要强制更改检测运行下一个tick,我们可以这样做:

export class App implements AfterViewChecked {

  show = false; // add one more property

  constructor(private cdRef : ChangeDetectorRef) { // add ChangeDetectorRef
    //...
  }
  //...
  ngAfterViewChecked() {
    let show = this.isShowExpand();
    if (show != this.show) { // check if it change, tell CD update view
      this.show = show;
      this.cdRef.detectChanges();
    }
  }

  isShowExpand()
  {
    //...
  }
}
Run Code Online (Sandbox Code Playgroud)

现场演示:https://plnkr.co/edit/UDMNhnGt3Slg8g5yeSNO?p=preview

  • 与 @Ziggler 相同,它也对我有用,仅在 ngAfterViewChecked 中使用 `this.cdRef.detectChanges();` (5认同)
  • 这对我有用。在我的ngAfterViewChecked方法中,我只有this.cdRef.detectChanges();。 (3认同)

Par*_*sha 23

实施AfterContentChecked方法。

constructor(
    private cdr: ChangeDetectorRef,
) {}

ngAfterContentChecked(): void {
   this.cdr.detectChanges();
}  
Run Code Online (Sandbox Code Playgroud)

  • 这个为我做到了<3 (4认同)

cs_*_*pil 18

出于某种原因,@Tiep Phan 的回答对我强制更改检测不起作用,但使用 setTimeout(也强制更改检测)可以。

我也只需要将它添加到有问题的行中,它与我在 ngOnInit 中已有的代码一起工作得很好,而不必添加 ngAfterViewInit。

例子:

ngOnInit() {
    setTimeout(() => this.loadingService.loading = true);
    asyncFunctionCall().then(res => {
        this.loadingService.loading = false;
    })
}
Run Code Online (Sandbox Code Playgroud)

更多细节在这里:https : //github.com/angular/angular/issues/6005


Nik*_*ani 15

在 ngAfterContentChecked 为我解决问题后导致更改检测器运行

示例如下:

import { ChangeDetectorRef,AfterContentChecked} from '@angular/core'
export class example implements OnInit, AfterContentChecked {
    ngAfterContentChecked() : void {
        this.changeDetector.detectChanges();
    }
}
Run Code Online (Sandbox Code Playgroud)

虽然,当我阅读一些文章时,这个问题在生产模式下得到解决,无需任何必要的修复。

以下是此类问题的可能原因:

它强制执行单向数据流:当我们的控制器类上的数据更新时,更改检测会运行并更新视图。

但是视图的更新本身不会触发进一步的更改,而这些更改又会触发对视图的进一步更新

https://blog.angular-university.io/how-does-angular-2-change-detection-really-work/


Ami*_*aei 6

为了解决这个问题,您可以将更改 *ngIf 状态的变量从ngAfterViewInit移动到ngOnInit构造函数。因为在调用 AfterViewInit 方法时不允许更改 html 的状态。

正如 @tiep-phan 所说,另一种方法是将 ChangeDetectorRef 传递给构造函数,并在 AfterViewInit 方法中更改 *ngIf 的状态后调用 this.chRef.detectChanges() 。


Ste*_*i J 6

我们还可以通过将changeDetection更改为OnPush来抑制抛出此ExpressionChangedAfterItHasBeenCheckedError。因此,不会执行额外的更改检测,因此不会引发错误。为此,您需要在.ts文件中添加装饰器的一部分,如下所示:ChangeDetectionStrategy.OnPush@Component

@Component({
  selector: 'your-component',
  templateUrl: 'your-component.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush
})
Run Code Online (Sandbox Code Playgroud)