表达式___被检查后已更改

TypeScript

宝儿

2020-05-26

为什么在这个简单的组件普拉克

@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 :)'
  }
}

抛出:

例外:表达式'我在App @ 0:5中是{{message}}'已被检查。先前的值:[我在App @ 0:5的{{message}}}中的'I'正在加载:('。当前值:'I's all done loading :)

当我正在做的所有事情都是在启动视图时更新一个简单的绑定吗?

第4178篇《表达式___被检查后已更改》来自Winter(https://github.com/aiyld/aiyld.github.io)的站点

9个回答
斯丁前端 2020.05.26

我认为最简单的解决方案如下:

  1. 进行一种将值分配给某个变量的实现,即通过函数或设置器。
  2. (static working: boolean)在存在该函数的类中创建一个类变量,每次调用该函数时,只要使它随便即可即可。在该函数内,如果working的值为true,则无需执行任何操作即可立即返回。否则,执行所需的任务。确保在任务完成后将该变量更改为false,即在代码行的末尾或在完成分配值后在subscription方法内!
乐米亚 2020.05.26

引发错误是因为调用ngAfterViewInit()时您的代码已更新意味着当ngAfterViewInit发生时,您的初始值已更改。如果在ngAfterContentInit()中调用它,则不会引发错误。

ngAfterContentInit() {
    this.updateMessage();
}
Tom凯 2020.05.26

使用数据表时出现类似错误。当您在另一个* ngFor数据表中使用* ngFor时,会发生此错误,因为它拦截了角度更改周期。因此,而不是在数据表中使用数据表,而要使用一个常规表或将mf.data替换为数组名称。这很好。

鱼二水 2020.05.26

因为我没有足够的声誉,所以我无法评论@Biranchi的帖子,但这为我解决了这个问题。

要注意的一件事!如果添加changeDetection:该组件上的ChangeDetectionStrategy.OnPush不起作用,并且其子组件(哑组件)也尝试将其添加到父组件。

这修复了该错误,但是我想知道它的副作用是什么。

神无 2020.05.26

您还可以使用rxjs Observable.timer函数创建计时器,然后更新订阅中的消息:                    

Observable.timer(1).subscribe(()=> this.updateMessage());
Tom凯 2020.05.26

之所以会出现此错误,是因为初始化后会立即更新现有值。因此,如果您在DOM中呈现现有值后更新新值,则它将正常工作。就像本文中提到的Angular Debugging“检查表达式后更改了它”

例如你可以使用

ngOnInit() {
    setTimeout(() => {
      //code for your new value.
    });

}

要么

ngAfterViewInit() {
  this.paginator.page
      .pipe(
          startWith(null),
          delay(0),
          tap(() => this.dataSource.loadLessons(...))
      ).subscribe();
}

如您所见,我在setTimeout方法中没有提到时间。由于它是浏览器提供的API,而不是JavaScript API,因此它将在浏览器堆栈中单独运行,并等待直到调用堆栈项完成。

菲利普·罗伯茨(Philip Roberts)在Youtube视频之一中解释了浏览器API调用概念的方式(事件循环是什么?)。

MonsterKK 2020.05.26

为此,我已经尝试了以上答案,但许多版本在Angular的最新版本(6或更高版本)中不起作用

我正在使用Material控件,该控件在完成第一次绑定后需要进行更改。

    export class AbcClass implements OnInit, AfterContentChecked{
        constructor(private ref: ChangeDetectorRef) {}
        ngOnInit(){
            // your tasks
        }
        ngAfterContentChecked() {
            this.ref.detectChanges();
        }
    }

因此,请添加我的答案,这有助于解决某些特定问题。

伽罗理查德 2020.05.26

您还可以在ngOnInt()-Method中将对updateMessage()的调用放入,至少对我有用

ngOnInit() {
    this.updateMessage();
}

在RC1中,这不会触发异常

乐米亚 2020.05.26

ngOnInit您只是因为更改了成员变量而不能使用message吗?

如果要访问对子组件的引用@ViewChild(ChildComponent),则确实需要使用ngAfterViewInit

肮脏的解决方法是updateMessage()在下一个事件循环中使用setTimeout 调用

ngAfterViewInit() {
  setTimeout(() => {
    this.updateMessage();
  }, 1);
}

问题类别

JavaScript Ckeditor Python Webpack TypeScript Vue.js React.js ExpressJS KoaJS CSS Node.js HTML Django 单元测试 PHP Asp.net jQuery Bootstrap IOS Android