简体   繁体   English

改变Angular中的检测周期 - 澄清?

[英]Change detection cycle in Angular - clarification?

Regarding ChangeDetectorRef , I already know that - 关于ChangeDetectorRef ,我已经知道 -

detectChanges actually triggers change detection while with - markForCheck - The actual change detection for the component is not scheduled but when it will happen in the future (either as part of the current or next CD cycle) detectChanges实际上触发了变化检测 - markForCheck的实际变化检测未被调度,但是将来会发生(当前或下一个CD循环的一部分)

Taken from here 取自这里

Looking at markForCheck - if it's not scheduled, so when will it run? 看看markForCheck - 如果没有安排,那么什么时候会运行? Obviously after Observables callback, async callbacks and setTimout and events. 显然是在Observables回调,异步回调和setTimout和事件之后。

The docs has a component with OnPush strategy 文档中有一个包含OnPush策略的组件

@Component({
  selector: 'cmp',
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `Number of ticks: {{numberOfTicks}}`
})
class Cmp {
  numberOfTicks = 0;

  constructor(private ref: ChangeDetectorRef) {
    setInterval(() => {
      this.numberOfTicks++;
      // the following is required, otherwise the view will not be updated
      this.ref.markForCheck();
    }, 1000);
  }
}

Question: 题:

If it marks for checking its ancestors, for the next cycle , so who ran the current cycle? 如果它标记为检查其祖先, 在下一个周期 ,那么谁运行当前周期? (Is it the prev setTimeout invocation?) (它是上一个setTimeout调用吗?)

Because this code is showing each second being replaced by another - in other words each second there is a change detection (?!). 因为这段代码显示每秒被另一个代替 - 换句话说每秒都有一个变化检测(?!)。

What is actually going on here via a POV of steps? 通过POV步骤实际发生了什么?

markForCheck , as you guessed, and as the name suggests, will tell the Angular to mark the component to be change-detectable for the next cycle. 正如您所猜测的那样, markForCheck ,正如其名称所暗示的那样,将告诉Angular将组件标记为可在下一个周期进行更改检测。

When you're writing setInterval, this is what you're actually writing: 当您编写setInterval时,这就是您实际编写的内容:

constructor(private ref: ChangeDetectorRef) {
    setInterval(() => {
      this.numberOfTicks++;
      // the following is required, otherwise the view will not be updated
      this.ref.markForCheck();

      detectChangesFromZoneJS(); // this is a psudo code, but you can imagine something like this will happen, which is patched by NGZone
     // Note that this is the last function that will always be called by Zone at the end of all the async events

    }, 1000);
}

This is handled by ZoneJS. 这由ZoneJS处理。

Zone monkey patches all of the async events, and when they finish, Zone will notify Angular and then Angular. 区域猴子修补了所有异步事件,当它们完成时,Zone会通知Angular,然后是Angular。 knows it's time to detect the changes ( update the view based on the latest model changes), but when you're component is OnPush is not going to detect the changes, unless there has special things happened inside the component, ( like a click event, or any of the @input 's is changed). 知道是时候检测更改(根据最新的模型更改更新视图),但是当你是组件时, OnPush不会检测到更改,除非组件内部发生特殊事情,(如点击事件) ,或任何@input的更改)。

So when you're deliberately saying markForCheck , you're basically saying: "I know you shouldn't detect the changes because it's OnPush only, but I'm telling you to detect it anyway" 所以,当你故意说markForCheck ,你基本上会说:“我知道你不应该检测到这些变化,因为它只是OnPush ,但我告诉你无论如何都要检测到它”

So here is step by step: 因此,这里是一步一步:

  1. Component is initialized, Angular will detect all the changes, your view is updated 组件已初始化,Angular将检测所有更改,您的视图已更新

  2. You run a setInterval, inside it, you're mutating your model, Angular knows it shouldn't update the view because it's OnPush 你在其中运行一个setInterval,你正在改变你的模型,Angular知道它不应该更新视图,因为它是OnPush

  3. the first interval's callback gets called, we're inside the first function, you're marking the component to be deliberately checked, we're at the end of the interval function ( still the first one interval). 第一个区间的回调被调用,我们在第一个函数内部,你正在标记要被故意检查的组件,我们在区间函数的末尾(仍然是第一个区间)。

  4. Zone notify's Anguar that an Async event is just finished, time to detect the changes 区域通知的Anguar刚刚完成Async事件,是检测更改的时间

  5. Angular looks at the OnPush and wants to ignore it, but remembers that you've marked the component to be checked by force Angular看看OnPush并想忽略它,但是记得你已经标记了要强制检查的组件

  6. the view get's updated 视图得到更新

  7. we go to the second interval and so on. 我们去第二个区间,依此类推。

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

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