简体   繁体   English

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

[英]Angular 4 detach change detection between children

I don't understand why even if I use ChangeDetectionStrategy.OnPush and changeDetectorRef.detach() the function ngDoCheck keep been called. 我不明白为什么即使我使用ChangeDetectionStrategy.OnPush和changeDetectorRef.detach()函数ngDoCheck一直被调用。 I have thousands of components in my app, and I'd like to block the changeDetection of child1 if an event (mouse click, etc) has been raised from child2. 我的应用程序中有数千个组件,如果从child2引发了一个事件(鼠标点击等),我想阻止child1的changeDetection。

Here is a plunker 这是一个掠夺者

As you can see I have a father component 如你所见,我有一个父组件

@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");
  }
}

and 2 identical children: 和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");
  }
}

If I start typing in the input of child1, the ngDoCheck function of child2 is called. 如果我开始输入child1的输入,则调用child2的ngDoCheck函数。

Think about having thousands of children, it get really slow... 想想有成千上万的孩子,它真的很慢......

Thank you! 谢谢!

That is the intended behavior, read Everything you need to know about change detection in Angular . 这是预期的行为,请阅读您需要了解的有关Angular中的更改检测的所有内容 Here is the quote: 这是引用:

  1. calls OnInit and ngDoCheck on a child component (OnInit is called only during first check) 在子组件上调用OnInit和ngDoCheck(仅在首次检查时调用OnInit)
  2. runs change detection for a child view (repeats the steps in this list) 运行子视图的更改检测(重复此列表中的步骤)

So as you can see the ngDoCheck is always triggered on the child component. 因此,您可以看到始终在子组件上触发ngDoCheck The OnPush check is performed after when trying to run change detection for the child component. 在尝试运行子组件的更改检测执行OnPush检查。 Here is the quote: 这是引用:

Finally, change detection for the current view is responsible for starting change detection for child views (operation 8). 最后,当前视图的更改检测负责启动子视图的更改检测(操作8)。 This is the place where state of the child component view is checked and if it's ChecksEnabled, then for this view the change detection is performed. 这是检查子组件视图状态的位置,如果是ChecksEnabled,则对于此视图执行更改检测。 Here is the relevant code: 这是相关代码:

viewState = view.state;
...
case ViewAction.CheckAndUpdate:
  if ((viewState & ViewState.ChecksEnabled) &&
    (viewState & (ViewState.Errored | ViewState.Destroyed)) === 0) {
    checkAndUpdateView(view);
  }
}

However, it will be called only for the top component on which the OnPush strategy is used. 但是,它仅针对使用OnPush策略的顶级组件调用。 It will not be called on child components: 它不会在子组件上调用:

     normal component
           |
  child OnPush component  <---- ngDoCheck called only for this component
           | 
    child component 1     <---- ngDoCheck is not called for this component
           |
    child component 2     <---- ngDoCheck is not called for this component

Why is it triggered? 为何触发?

It's triggered to give you opportunity to perform your own custom logic inside this hook and choose to run change detection cycle once even if @Input s haven't changed: 触发它为您提供在此挂钩内执行自己的自定义逻辑的机会,并选择运行更改检测周期,即使@Input未更改:

class OnPushComponent {
   constructor(private cd: ChangeDetectorRef) {}

   ngDoCheck() {
      if (some check) {
          this.cd.markForCheck();
      }
   }
}

Also see Angular ngDoCheck() gets called even with ChangeDetectionStrategy.OnPush this answer for real use case example. 另请参阅Angular ngDoCheck(),即使使用ChangeDetectionStrategy.OnPush,这个答案也适用于实际用例示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM