You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 20:38:22