表达式 ___ 被检查后发生了变化 [英] Expression ___ has changed after it was checked

查看:36
本文介绍了表达式 ___ 被检查后发生了变化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么这个简单的组件plunk

Why is the component in this simple 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]

EXCEPTION: Expression 'I'm {{message}} in App@0:5' has changed after it was checked. Previous value: 'I'm loading :( '. Current value: 'I'm all done loading :) ' in [I'm {{message}} in App@0:5]

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

when all I'm doing is updating a simple binding when my view is initiated?

推荐答案

首先,请注意,只有在开发模式下运行应用程序时才会抛出此异常(这是 beta-0 的默认情况): 如果你调用 enableProdMode() 在引导应用程序时,它不会被抛出(查看更新的 plunk).

First, note that this exception will only be thrown when you're running your app in dev mode (which is the case by default as of beta-0): If you call enableProdMode() when bootstrapping the app, it won't get thrown (see updated plunk).

其次,不要那样做,因为抛出这个异常是有充分理由的:简而言之,在开发模式下,每轮更改检测之后都会紧跟第二轮验证没有自第一次结束以来,绑定发生了变化,因为这表明变化是由变化检测本身引起的.

Second, don't do that because this exception is being thrown for good reason: In short, when in dev mode, every round of change detection is followed immediately by a second round that verifies no bindings have changed since the end of the first, as this would indicate that changes are being caused by change detection itself.

在你的 plunk 中,绑定 {{message}} 被你对 setMessage() 的调用改变了,这发生在 ngAfterViewInit钩子,它作为初始变化检测回合的一部分发生.但这本身并没有问题 - 问题在于 setMessage() 更改了绑定但不会触发新一轮的更改检测,这意味着直到未来的某个轮才会检测到此更改的变化检测是在其他地方触发的.

In your plunk, the binding {{message}} is changed by your call to setMessage(), which happens in the ngAfterViewInit hook, which occurs as a part of the initial change detection turn. That in itself isn't problematic though - the problem is that setMessage() changes the binding but does not trigger a new round of change detection, meaning that this change won't be detected until some future round of change detection is triggered somewhere else.

要点:任何更改绑定的操作都需要在更改时触发一轮更改检测.

根据所有请求更新如何执行此操作的示例:@Tycho 的解决方案有效,答案 @MarkRajcok 指出.但坦率地说,他们都让我觉得丑陋和错误,就像我们在 ng1 中习惯依赖的那种黑客.

Update in response to all the requests for an example of how to do that: @Tycho's solution works, as do the three methods in the answer @MarkRajcok pointed out. But frankly, they all feel ugly and wrong to me, like the sort of hacks we got used to leaning on in ng1.

可以肯定的是,在偶尔情况下,这些 hack 是合适的,但是如果您使用它们而不仅仅是 非常 偶尔,这是一个迹象你正在与框架作斗争,而不是完全接受它的反应性质.

To be sure, there are occasional circumstances where these hacks are appropriate, but if you're using them on anything more than a very occasional basis, it's a sign that you're fighting the framework rather than fully embracing its reactive nature.

恕我直言,一种更惯用的Angular2 方式"接近这个问题:( 笨拙)

IMHO, a more idiomatic, "Angular2 way" of approaching this is something along the lines of: (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 :)')
  }
}

这篇关于表达式 ___ 被检查后发生了变化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆