本文介绍了当投影组件在祖先中设置值时,出现“检查后更改"错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当投影组件在祖先组件中设置值时,出现检查后更改"错误.这是我的问题的再现: plnkr.co/edit/jJNFsJdf1KDSF3Fqhfb8

I'm getting a 'change after check' error when a projected component sets a value in an ancestor component. Here is a reproduction of my issue: plnkr.co/edit/jJNFsJdf1KDSF3Fqhfb8

@Component({
  selector: 'app-component',
  template: `
    <test-component>
      <ng-template #tpl>
        <projected-component [rootComponent]="this"></projected-component>
      </ng-template>
    </test-component>
    {{change}}
  `
})
export class AppComponent {
  change = 0;
}


@Component({
  selector: 'test-component',
  template: `
    <ng-template [ngTemplateOutlet]="tplRef"></ng-template>
  `
})
export class TestComponent {
  @ContentChild('tpl') tplRef: TemplateRef<any>;
}


@Component({
  selector: 'projected-component',
  template: ` 
    <div>{{parent}}</div>
  `
})
export class ProjectedComponent {
  @Input() rootComponent: TestApp;

  ngOnInit() {
    this.rootComponent.change++;
  }
}

错误是:

ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'null: 0'. Current value: 'null: 1'.

我首先从嵌套表格模式由Matt Brophy撰写.这是一个很好的模式,但是我认为他可能忽略了这个问题,或者在Angular的早期版本中这不是问题.我最初的问题是此处.由于没有简化的实时复制,我在解决方案方面没有获得成功.

I first came upon this problem from a nested form pattern by Matt Brophy. It's a beautiful pattern, but I think he may have overlooked this issue, or it wasn't an issue in earlier versions of Angular. My original question is here. I didn't have success with help on a solution, since I didn't have a simplified, live reproduction.

如何设置它而不会出现错误?

How can I set this up without getting errors?

推荐答案

问题是,您正在以相同的更改检测周期更改来自父级的数据.您只需将更改包装在setTimeout()调用中以确保它在更改检测周期结束后运行,就可以防止抛出该错误.

The problem is that you are changing data from the parent in the same change detection cycle. You can stop that error from being throw by simply wrapping your change in a setTimeout() call to ensure that it runs after the change detection cycle completes.

ngOnInit() {
    console.log(this.rootComponent);
    setTimeout(() => this.rootComponent.change++);
}

您通常不会遇到这些问题,因为通常是触发数据更改的某些用户事件,而不是在更改检测生命周期中运行的某些方法(至少不会更改父数据).

You typically won't run into these issues tho because it typically is some user event that triggers a change in data, not some methods running during the change detection lifecycle (well at least not change parent data).

话虽这么说,但是通常最好不要修改另一个组件拥有的数据.正如@Harry Ninh所提到的,最好广播一个事件以通知父项需要更新数据(在这种情况下,您仍然需要用setTimeout()包装,因为您仍将广播该事件到在相同的更改检测周期中更改父项中的数据.

That being said, it typically isn't best to be modifying data that is owned by another component though. As @Harry Ninh mentioned, it would be best to broadcast out an event to notify the parent that the data needs to be updated (in this case you would still need to wrap with the setTimeout() since you would still be broadcasting that event to change data in the parent in the same change detection cycle).

这篇关于当投影组件在祖先中设置值时,出现“检查后更改"错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-02 10:17