Angular,setInterval导致组件不间断地更新其UI

时间:2017-11-13 09:36:20

标签: angular

我需要在我的一个子组件中有一个setInterval来检查我的DIV高度之一。问题是我发现这个setInterval会导致我的组件UI不停更新。事件父组件也不停更新自身。

@Component({
  selector: 'app-test-comp',
  template: `
    <ul>
      <li *ngFor="let num of [1,2,3]">
        {{ print(num) }}
      </li>
    </ul>
  `,
})
class TestComponent {
  private attr: Date;
  constructor() {
    setInterval(() => {}, 1000)
  }
  print(num) {
    return num + ' ' + new Date();
  }
}

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2>Hello {{name}}</h2>
      <ul>
      <li *ngFor="let num of [1,2,3,4]">{{ test(num) }}</li>
      </ul>
      <app-test-comp></app-test-comp>
    </div>
  `,
})
export class App {
  name:string;
  constructor() {
    this.name = `Angular! v${VERSION.full}`
  }
  test(num) {
    return num + ' ' + new Date()
  }
}

PlunkerLink

请参阅上面的plunker链接,它清楚地显示根组件及其子组件不断更新其UI。如果我在app.ts第18行删除了setInterval,它将正常运行。

我想知道导致不间断更新UI问题的原因以及如何防止这种情况。

2 个答案:

答案 0 :(得分:1)

Angular取决于zone.js和区域猴子补丁本地方法,如setTimeoutsetInterval,因此,如果您使用的是setInterval,那么您实际上正在使用修补版本,因此angular正在更新UI。

为防止此角度有一个名为NgZone的服务,它实现了一种在角区域外运行方法的方法。

例如:

import { NgZone } from '@angular/core';

constructor(private _zone: NgZone) { 
  this._zone.runOutsideAngular(() => {
    setInterval(() => {}, 1000); // this runs outside of the angular zone
    this._zone.run(() => {
      // this runs inside the angular zone
    });

  });
}

有关角度区域的更详细说明,请参阅此article

答案 1 :(得分:1)

setInterval这样的异步方法由zone.js进行猴子修补,这是一个由angular使用的库。 模型更改后更新视图。猴子修补意味着扩展方法的功能。 因此,每当调用setInterval时,都会触发角度变化检测以更新视图。

您可以在角度之外运行代码以避免运行更改检测:

constructor(
    private zone: NgZone
) {
    this.zone.runOutsideAngular(() => {
        setInterval(() => {}, 1000)
    })
}

我已使用以上示例更新了您的plnkr