我正在构建一个倒计时器组件并尝试在每秒内显示更新的“秒”值,但我在 UI 上没有看到任何更新
当我不使用外部区域态度时,页面只是空白并无限加载。
.ts 文件
import { Component, ElementRef, NgZone, OnInit, ViewChild } from '@angular/core';
@Component({
selector: 'app-countdown',
templateUrl: './countdown.component.html',
styleUrl: './countdown.component.css'
})
export class CountdownComponent implements OnInit {
static initialized: boolean = false;
weddingDate: Date = new Date('2024-08-17T15:00:00');
constructor(private zone: NgZone) {}
@ViewChild('seconds') seconds: ElementRef;
ngOnInit(): void {
if(!CountdownComponent.initialized) {
this.countdown(this.zone);
CountdownComponent.initialized = true;
}
}
countdown(zone: NgZone) {
zone.runOutsideAngular(() => {
setInterval(() => {
this.seconds.nativeElement.innerHTML = (this.weddingDate.getTime() - new Date().getTime()) / 1000;
console.log(this.seconds.nativeElement.innerHTML);
}, 1000);
})
}
}
html 文件
<div #seconds> </div>
NG0500错误意味着您的项目使用服务器端渲染(SSR)。这意味着您的应用程序首先在服务器上运行所有内容,等待异步任务完成,然后将其发送到应用程序继续执行的客户端。
运行
setInterval
会阻止服务器完成渲染,因为始终有异步任务要执行。这就是为什么将其包装到 zone.runOutsideAngular
会产生差异,因为 Angular 不再监视它,但这种包装也使这些更改对于客户端的更改检测不可见,这就是计数器不在那里更新的原因。
如果你想使用SSR并使你的代码正常运行,你可以添加对平台的检查,并仅在客户端启动计数器:
@Component({
selector: 'app-root',
standalone: true,
template: `<div>{{ secondsLeft }}</div>`,
})
export class AppComponent {
weddingDate: Date = new Date('2024-08-17T15:00:00');
secondsLeft: number;
constructor(@Inject(PLATFORM_ID) private platform: Object) {}
ngOnInit(): void {
if (!isPlatformServer(this.platform)) {
this.countdown();
}
}
countdown() {
setInterval(() => {
this.secondsLeft = (this.weddingDate.getTime() - new Date().getTime()) / 1000;
}, 1000);
}
}
请注意,我还删除了更新元素的
innerHTML
,因为这在 Angular 中通常是一种不好的做法,并会导致 NG0500 错误。使用绑定并避免直接 DOM 操作总是更好。
如果您不完全了解 SSR 如何影响您的应用程序,我强烈建议您不要使用 SSR。禁用它的最简单方法是通过删除
angular.json
部分中的以下行来更改 architect > build > options
文件:
"prerender": false,
"ssr": {
"entry": "server.ts"
}
它会禁用 SSR,您可能需要删除一些与 SSR 相关的文件(它们的文件名后缀为
server
)。