我需要在我的一个子组件中有一个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()
}
}
请参阅上面的plunker链接,它清楚地显示根组件及其子组件不断更新其UI。如果我在app.ts第18行删除了setInterval,它将正常运行。
我想知道导致不间断更新UI问题的原因以及如何防止这种情况。
答案 0 :(得分:1)
Angular取决于zone.js
和区域猴子补丁本地方法,如setTimeout
和setInterval
,因此,如果您使用的是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