我正在尝试在我的 Angular 应用程序中制作一个简单的数字时钟,但目前我只是让它显示一个计数器,同时我弄清楚到底发生了什么:
在clock.component.html中:
<div class="time" id="time">{{ secondsPassed }}</div>
在clock.component.ts中:
@Component({
selector: 'app-clock',
standalone: true,
imports: [],
templateUrl: './clock.component.html',
styleUrl: './clock.component.scss'
})
export class ClockComponent implements OnInit, OnDestroy {
secondsPassed: number;
timer: any;
constructor() {
this.secondsPassed = 0;
}
ngOnInit(): void {
this.startTimer();
}
ngOnDestroy(): void {
if (this.timer) {
clearInterval(this.timer);
}
}
startTimer() {
this.timer = setInterval(() => {
this.secondsPassed++;
console.log(this.secondsPassed);
}, 1000)
}
}
每当我执行服务并继续 localhost:4200 时,它将永远卡在旋转的加载圈上,除非我手动输入 localhost:4200/index.html,此时它将正确显示计时器并更新。
我尝试了很多不同的东西,包括 rxjs 订阅和异步管道,但没有任何效果。我什至尝试在 Angular 区域之外运行,但计时器不会更新。
我注意到的一件非常奇怪的事情是,每当我保存对代码的更改并在 Angular 本地服务器运行时重建它时,它就会看起来好像有两个计时器在运行,所以我不确定 ngOnDestroy 是否被调用以及第一个还没清除?我对 Angular 还很陌生,所以我不知道这是否与我的问题有关。
感谢您的帮助!
出于某种原因,这个问题的答案有效。我不知道为什么,但至少它解决了我的问题:)
我也遇到了同样的问题,花了很长时间才找到解决方案。
随着 Angular 17 中引入 SSR,页面的渲染发生在服务器上,从而产生包含初始页面状态的初始 HTML 内容。这会导致在计时器或间隔运行时渲染无法完成。
afterNextRender
方法来解决,该方法必须在可注入上下文中调用,最好是在 constructor
中调用。
afterNextRender(() => {
setInterval(() => {
console.log('Interval triggered');
// Put your code here
ngZone.run(() => {
// Put your ui changes here
});
}, 10000);
}, {phase: AfterRenderPhase.Write});
UI 更改必须再次在 Angular 环境中进行。
RenderPhase
。
您问题的完整组成部分:
import {afterNextRender, AfterRenderPhase, Component, NgZone, OnDestroy, OnInit} from "@angular/core";
@Component({
selector: 'app-clock',
standalone: true,
imports: [],
templateUrl: './clock.component.html',
styleUrl: './clock.component.scss'
})
export class ClockComponent implements OnInit, OnDestroy {
secondsPassed: number;
timer: any;
constructor(private ngZone: NgZone) {
this.secondsPassed = 0;
afterNextRender(() => {
this.startTimer();
}, {phase: AfterRenderPhase.Write});
}
ngOnInit(): void {
//this.startTimer();
}
ngOnDestroy(): void {
if (this.timer) {
clearInterval(this.timer);
}
}
startTimer() {
this.timer = setInterval(() => {
this.ngZone.run(() => {
this.secondsPassed++;
});
console.log(this.secondsPassed);
}, 1000)
}
}