儿童之间的角度4分离变化检测

use*_*955 6 angular2-changedetection angular

我不明白为什么即使我使用ChangeDetectionStrategy.OnPush和changeDetectorRef.detach()函数ngDoCheck一直被调用.我的应用程序中有数千个组件,如果从child2引发了一个事件(鼠标点击等),我想阻止child1的changeDetection.

这是一个掠夺者

如你所见,我有一个父组件

@Component({
  selector: 'my-app',
  template: `     
    <app-child1 test="test"></app-child1>
    <app-child2 test="test"></app-child2> `,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppComponent {
  test = 'test';

constructor() { }

  ngDoCheck() {
    console.log("### ngDoCheck app component");
  }
}
Run Code Online (Sandbox Code Playgroud)

和2个相同的孩子:

@Component({
  selector: 'app-child1',
  template: `<input type="text" [(ngModel)]="test" /><br/> `,
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class Child1Component implements OnInit {
  @Input()
  test: string;

  constructor(public cd: ChangeDetectorRef) { }

  ngAfterViewInit() {
      console.log("###### DETACH child 1");
      this.cd.detach();

  }

  ngDoCheck() {
    console.log("### ngDoCheck child 1");
  }
}
Run Code Online (Sandbox Code Playgroud)

如果我开始输入child1的输入,则调用child2的ngDoCheck函数.

想想有成千上万的孩子,它真的很慢......

谢谢!

Max*_*kyi 3

这就是预期的行为,请阅读关于 Angular 中的更改检测您需要了解的一切。这是引用:

\n\n
\n
    \n
  1. 在子组件上调用 OnInit 和 ngDoCheck (OnInit 仅在第一次检查期间调用)
  2. \n
  3. 对子视图运行更改检测(重复此列表中的步骤)
  4. \n
\n
\n\n

正如您所看到的,ngDoCheck总是在子组件上触发。检查OnPush在之后执行的在尝试对子组件运行更改检测这是引用:

\n\n
\n

最后,当前视图的更改检测负责启动子视图的更改检测(操作 8)。这是检查子组件视图状态的位置,如果它\xe2\x80\x99s\n ChecksEnabled,则对此视图执行更改检测。\n 以下是相关代码:

\n
\n\n
viewState = view.state;\n...\ncase ViewAction.CheckAndUpdate:\n  if ((viewState & ViewState.ChecksEnabled) &&\n    (viewState & (ViewState.Errored | ViewState.Destroyed)) === 0) {\n    checkAndUpdateView(view);\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

但是,只会针对其上的顶部组件调用它OnPush。它不会在子组件上调用:

\n\n
     normal component\n           |\n  child OnPush component  <---- ngDoCheck called only for this component\n           | \n    child component 1     <---- ngDoCheck is not called for this component\n           |\n    child component 2     <---- ngDoCheck is not called for this component\n
Run Code Online (Sandbox Code Playgroud)\n\n

为什么会被触发?

\n\n

触发它是为了让您有机会在此挂钩内执行您自己的自定义逻辑,并选择运行一次更改检测周期,即使@Inputs 没有更改:

\n\n
class OnPushComponent {\n   constructor(private cd: ChangeDetectorRef) {}\n\n   ngDoCheck() {\n      if (some check) {\n          this.cd.markForCheck();\n      }\n   }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

另请参阅即使使用 ChangeDetectionStrategy.OnPush 这个答案也会调用 Angular ngDoCheck()以获取实际用例示例。

\n