为什么这个组件在这个简单的砰砰声中

@Component({
  selector: 'my-app',
  template: `<div>I'm {{message}} </div>`,
})
export class App {
  message:string = 'loading :(';

  ngAfterViewInit() {
    this.updateMessage();
  }

  updateMessage(){
    this.message = 'all done loading :)'
  }
}

扔:

例外:表达式'I'm {{message}} in App@0:5'在被检查后发生了变化。之前的值:'I'm loading:('。当前值:'I'm all done loading:)' in [I'm {{message}} in App@0:5]

当我所做的一切都是更新一个简单的绑定时,我的视图被启动?


当前回答

简单:首先在你的组件结构中分离/移除变更检测,然后在ngAfterViewInit()方法中启用detectChanges()

constructor(private cdr: ChangeDetectorRef) {
  this.cdr.detach() // detach/remove the change detection here in constructor
}


ngAfterViewInit(): void {
  // do load objects or other logics here
  
  // at the end of this method, call detectChanges() method.
  this.cdr.detectChanges(); // enable detectChanges here and you're done.
}

其他回答

我通过从angular core中添加ChangeDetectionStrategy来解决这个问题。

import {  Component, ChangeDetectionStrategy } from '@angular/core';
@Component({
  changeDetection: ChangeDetectionStrategy.OnPush,
  selector: 'page1',
  templateUrl: 'page1.html',
})

我不能评论@Biranchi的帖子,因为我没有足够的声誉,但它为我解决了这个问题。

有一件事要注意! 如果添加changeDetection: ChangeDetectionStrategy。OnPush在组件上没有工作,它是一个子组件(哑组件)尝试添加到父组件也。

这修复了bug,但我想知道这有什么副作用。

简单:首先在你的组件结构中分离/移除变更检测,然后在ngAfterViewInit()方法中启用detectChanges()

constructor(private cdr: ChangeDetectorRef) {
  this.cdr.detach() // detach/remove the change detection here in constructor
}


ngAfterViewInit(): void {
  // do load objects or other logics here
  
  // at the end of this method, call detectChanges() method.
  this.cdr.detectChanges(); // enable detectChanges here and you're done.
}

关于ExpressionChangedAfterItHasBeenCheckedError错误的一切你需要知道的文章详细解释了这种行为。

你设置的问题是ngAfterViewInit生命周期钩子是在变更检测处理DOM更新后执行的。你在这个钩子中有效地改变了模板中使用的属性,这意味着DOM需要重新渲染:

  ngAfterViewInit() {
    this.message = 'all done loading :)'; // needs to be rendered the DOM
  }

这将需要另一个变更检测周期,而Angular在设计上只运行一个摘要周期。

你基本上有两种解决方法:

使用setTimeout, Promise异步更新属性。然后在模板中引用异步可观察对象 在DOM更新之前执行钩子中的属性更新- ngOnInit, ngDoCheck, ngAfterContentInit, ngAfterContentChecked。

我从AfterViewInit切换到AfterContentChecked,它为我工作。

流程如下

在构造函数中添加依赖项: 构造函数(私有cdr: ChangeDetectorRef) {} 在实现方法代码中调用你的登录: ngAfterContentChecked () { this.cdr.detectChanges (); //调用或添加您的代码 }