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

标签 javascript angular

关于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)

Taken from here

查看 markForCheck - 如果没有安排,那么它什么时候运行?显然在 Observables 回调、异步回调和 setTimout 和事件之后。

The docs有一个带有 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);
  }
}

问题:

如果它标记为检查其祖先,下一个周期,那么谁运行了当前周期? (它是上一个 setTimeout 调用吗?)

因为这段代码显示每一秒都被另一个替换——换句话说,每一秒都有一个变化检测(?!)。

通过步骤的 POV,这里实际上发生了什么?

最佳答案

markForCheck,正如您猜到的那样,顾名思义,它将告诉 Angular 将组件标记为下一个周期的变化可检测。

当您编写 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);
}

这由 ZoneJS 处理。

Zone monkey 修补所有异步事件,当它们完成时,Zone 会通知 Angular,然后通知 Angular。知道是时候检测变化了(根据最新的模型变化更新 View ),但是当你的组件是 OnPush 时不会检测到变化,除非内部发生了特殊的事情组件,(如点击事件,或任何 @input 的更改)。

所以当你故意说 markForCheck 时,你基本上是在说:“我知道你不应该检测这些变化,因为它只是 OnPush,但我'我告诉你无论如何都要检测它”

所以这里是一步一步:

  1. 组件已初始化,Angular 将检测所有更改,您的 View 已更新

  2. 你运行一个 setInterval,在它里面,你正在改变你的模型,Angular 知道它不应该更新 View ,因为它是 OnPush

  3. 第一个间隔的回调被调用,我们在第一个函数内,您正在标记要有意检查的组件,我们在间隔函数的末尾(仍然是第一个间隔)。

  4. Zone 通知 Anguar 异步事件刚刚结束,是时候检测变化了

  5. Angular 查看 OnPush 并想忽略它,但记住您已将组件标记为强制检查

  6. View 得到更新

  7. 我们进入第二个间隔,依此类推。

关于javascript - Angular 中的更改检测周期 - 澄清?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47923376/

相关文章:

javascript - ReactJS:TypeError:无法读取未定义的属性 'map'

javascript - jQuery .fadeIn() 工作但 .slideDown() 和 .animate() 不工作

javascript - 根据渲染函数中的前一个状态设置状态

javascript - Ember JS 索引路由

angular - ionic CLI 启动 : starterkit v3?

javascript - 如何将数字过滤器添加到 Angular 6 中的 Algolia ais-instantsearch 组件

javascript - Unhandled Promise rejection : push. on is not a function

angular - TypeError : this. sqlites.executeSql 不是函数

c# - 尝试上传具有 Angular 2 的文档时,Web API 中的文件计数始终为零

Angular 应用程序在 nginx 上运行并在附加的 nginx 反向代理后面