Angular 17组件运行正常但命令行报window is not defined错误
Angular 17 SSR下window未定义问题解析
问题原因
你遇到的矛盾点核心在于:浏览器端运行时window是浏览器提供的全局对象,所以组件功能正常;但SSR(服务器端渲染)阶段是在Node.js环境执行的,这里不存在浏览器的window对象,而ngOnInit钩子会在服务器渲染组件初始状态时被调用,因此命令行会抛出window is not defined的错误。
你能在浏览器里正常访问window,是因为组件在浏览器端完成水合(hydration)后,浏览器环境提供了这个全局对象,但服务器端渲染过程中并没有。
操作问题
你直接在ngOnInit中访问window时,没有做环境判断,忽略了SSR的服务器执行阶段。Angular SSR会先在服务器端生成组件的静态HTML,这时候代码里的window引用就会触发错误。
修复方案
可以通过Angular提供的PLATFORM_ID来判断当前运行环境,仅在浏览器环境下执行window相关逻辑:
import { OnInit, Component, HostListener, Inject, PLATFORM_ID } from '@angular/core'; import { isPlatformBrowser } from '@angular/common'; import { AppConstants } from '../../common/constants'; @Component({ selector: 'app-video-player', standalone: true, imports: [], templateUrl: './video-player.component.html', styleUrl: './video-player.component.scss', }) export class VideoPlayerComponent implements OnInit { videoStyle: any; constructor(@Inject(PLATFORM_ID) private platformId: Object) {} ngOnInit(): void { // 仅在浏览器环境下执行窗口尺寸初始化 if (isPlatformBrowser(this.platformId)) { this.generateVideoStyle(window.innerWidth, window.innerHeight); } } generateVideoStyle(inpWidth: number, inpHeight: number): void { let playerWidth, playerHeight, playerMarginTop: number; playerWidth = 0.9 * inpWidth; if (playerWidth > AppConstants.MAX_VIDEO_WIDTH) { playerWidth = AppConstants.MAX_VIDEO_WIDTH; } playerHeight = playerWidth * AppConstants.VIDEO_ASPECT_RATIO; if (playerHeight > inpHeight) { playerHeight = 0.9 * inpHeight; playerWidth = playerHeight / AppConstants.VIDEO_ASPECT_RATIO; } playerMarginTop = (inpHeight - playerHeight) / 2.0; this.videoStyle = { height: `${playerHeight}px`, width: `${playerWidth}px`, marginTop: `${playerMarginTop}px` }; } @HostListener('window:resize', ['$event']) onResize(event: any) { this.generateVideoStyle(event.target.innerWidth, event.target.innerHeight); } }
另一种方式是通过注入DOCUMENT间接获取窗口对象(同样需要配合环境判断):
import { DOCUMENT } from '@angular/common'; // 构造函数中注入DOCUMENT constructor( @Inject(PLATFORM_ID) private platformId: Object, @Inject(DOCUMENT) private document: Document ) {} // 在ngOnInit中使用 ngOnInit(): void { if (isPlatformBrowser(this.platformId)) { const window = this.document.defaultView; this.generateVideoStyle(window.innerWidth, window.innerHeight); } }
这样修改后,服务器端渲染时会跳过window相关逻辑,不再报错,同时浏览器端的自适应功能完全不受影响。
内容的提问来源于stack exchange,提问作者Shiv Kumar
相关产品推荐
相关产品推荐

