Angular 17 不使用 setInterval 更新视图

问题描述 投票:0回答:1

我正在构建一个倒计时器组件并尝试在每秒内显示更新的“秒”值,但我在 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>

angular view timer setinterval countdown
1个回答
0
投票

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
)。

© www.soinside.com 2019 - 2024. All rights reserved.