错误ExpressionChangedAfterItHasBeenCheckedError究竟如何与角度检测一起工作?

问题描述 投票:0回答:1

我读了很多文章,但仍然不明白角度变化检测的一些情况。我得到以下示例: Angular 应用程序在所有组件中实现了 OnInit、AfterViewInit、DoCheck、AfterViewChecked:

  1. 家长
  2. 孩子
  3. 深孩子

仅在父级中我实现了流行的加载示例(以及 HTML 中的

*ngIf="isLoading"
):

export class AppComponent
  implements OnInit, AfterViewInit, DoCheck, AfterViewChecked
{
  isLoading = false;
  constructor(private changeDetectorRef: ChangeDetectorRef) {}

  ngAfterViewInit(): void {
    this.isLoading = true;
    console.log('parent - after view init');
  }

  ngAfterViewChecked(): void {
    console.log('AFTER CHECK');
  }

  ngDoCheck(): void {
    console.log('parent - do check');
  }
  ngOnInit(): void {
    console.log('parent - init');
    
  }
}

输出(不加载

this.isLoading = true;
)是:

parent - init
parent - do check
Child - init
Child - do check
DeepChild - init
DeepChild - do check
DeepChild - after view init
DeepChild - after check
Child - after view init
Child - after check
parent - after view init
parent - after view check
<with assigning loading value as in code above here I got expression changed error>
<and after that I got some more checks generated>
parent - do check
Child - do check
DeepChild - do check
DeepChild - after check
Child - after check
parent - after check

我有以下问题:

  1. 为什么我会收到额外的支票?

  2. 如果我添加加载,我会收到错误

    ExpressionChangedAfterItHasBeenCheckedError
    ,我知道这是在检查视图之后,但我得到了额外的检查,所以为什么问题仍然存在?

  3. 如果我添加changeDetectorRef并手动检测更改,问题就解决了,但为什么呢?好吧,我触发了下一个检测,但是在私钥中检查后仍然有一个表达式发生了变化,那么为什么触发下一个只是解决它呢?

  4. 此 detectorChanges 仅在子组件中触发

    doCheck
    。尽管我在父组件中触发它,但它并没有在父组件中调用检测?

这里是 stackblitz 参考 - https://stackblitz.com/edit/angular-ivy-m6hbk2?file=src%2Fapp%2Fapp.component.ts

angular angular2-changedetection angular-lifecycle-hooks
1个回答
0
投票

您希望应用程序中的单向数据流。在组件生命周期中,Angular 将数据从父级渲染到子级。 Angular 有一个开发检查,以便在该周期中渲染整个视图后,它会继续运行从父级到子级的整个数据渲染以确保没有任何更改。在生产中,第二次检查不会运行,并且更改的数据不会呈现为在该检测周期中已更改。

如果您设置了

isLoading = false;
并且渲染了父级,然后您立即更改了该值,那么您就破坏了这个单向数据流。尽管您之后更改了此设置,但孩子们仍将被渲染为
isLoading = false;
。强制更改检测在父级上运行两次可以“解决”问题,因为父级将使用可在生产中使用的更新值进行渲染。但这是一种反模式,引入检测周期来修复不良数据流。

在使用 Angular 4 年多的时间里,我从未在任何代码中使用过

ngDoCheck
,我不建议花很长时间来尝试理解它。

© www.soinside.com 2019 - 2024. All rights reserved.