表达式___在检查后发生了变化

新手上路,请多包涵

为什么这个简单的 plunk 中的组件是

@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’ 在检查后发生了变化。上一个值:’我正在加载:(‘。当前值:’我已经完成加载:)’ in [I’m {{message}} in App@0:5]

当我正在做的只是在我的视图启动时更新一个简单的绑定?

原文由 drew moore 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 447
2 个回答

首先,请注意,仅当您在开发模式下运行您的应用程序时才会抛出此异常(从 beta-0 开始默认为这种情况):如果您在引导应用程序时调用 enableProdMode() ,它不会被抛出( 请参阅更新的 plunk )。

其次, 不要这样做, 因为抛出此异常是有充分理由的:简而言之,在开发模式下,每一轮更改检测之后都会立即进行第二轮验证,该第二轮验证自第一轮结束以来没有任何绑定发生更改,因为这表明更改是由更改检测本身引起的。

在您的 plunk 中,绑定 {{message}} 被您调用 setMessage() 更改,这发生在 ngAfterViewInit 钩子中,作为初始更改检测的一部分转动。但这本身并没有问题 - 问题是 setMessage() 更改了绑定但不会触发新一轮的更改检测,这意味着在未来的某轮更改检测之前不会检测到此更改在其他地方触发。

要点: 任何改变绑定的事情都需要触发一轮变化检测

更新以响应有关如何执行此操作的示例的所有请求:@Tycho 的解决方案有效,@MarkRajcok 指出 的答案 中的三种方法也有效。但坦率地说,它们都让我觉得丑陋和错误,就像我们习惯在 ng1 中依赖的那种 hack。

可以肯定的是,在某些情况下这些 hack 是合适的,但如果 只是 偶尔 使用它们,这表明你正在与框架抗争,而不是完全接受它的反应性质。

恕我直言,一种更惯用的“Angular2 方式”接近这一点是这样的:( plunk

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

  ngAfterViewInit() {
    this.message.next('all done loading :)')
  }
}

原文由 drew moore 发布,翻译遵循 CC BY-SA 3.0 许可协议

您也可以尝试将 this.updateMessage(); 放在 ngOnInit 下,如下所示:

 ngOnInit(): void {
  this.updateMessage();
}

原文由 Marina Helmy 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进