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

解决NGUniversal中window is not defined错误

Angular SSR 解决 window is not defined 问题(Angular 16.2.12 + ng-universal)

针对你遇到的服务端渲染时window对象未定义的问题,提供以下几种实用解决方式:

方法1:通过PLATFORM_ID判断环境初始化

利用Angular提供的PLATFORM_ID标识当前运行环境,仅在浏览器端初始化滚动监听:

import { Component, Inject, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
import { fromEvent, Observable } from 'rxjs';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  private ScrollWatcher!: Observable<Event>;

  constructor(@Inject(PLATFORM_ID) private platformId: Object) {
    // 仅在浏览器环境下执行window相关逻辑
    if (isPlatformBrowser(this.platformId)) {
      this.ScrollWatcher = fromEvent(window, 'scroll');
      // 这里添加滚动事件的订阅逻辑
      // this.ScrollWatcher.subscribe(event => { /* 处理滚动 */ });
    }
  }
}

方法2:使用浏览器专属生命周期钩子

ngAfterViewInit是仅在浏览器端渲染完成后才会触发的生命周期钩子,SSR过程不会执行,可安全访问window:

import { Component, AfterViewInit } from '@angular/core';
import { fromEvent, Observable } from 'rxjs';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit {
  private ScrollWatcher!: Observable<Event>;

  ngAfterViewInit(): void {
    this.ScrollWatcher = fromEvent(window, 'scroll');
    // 添加滚动事件处理逻辑
  }
}

方法3:结合DOCUMENT注入规范访问window

遵循Angular依赖注入规范,通过DOCUMENT获取window对象,同时配合环境判断:

import { Component, Inject, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser, DOCUMENT } from '@angular/common';
import { fromEvent, Observable } from 'rxjs';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  private ScrollWatcher!: Observable<Event>;

  constructor(
    @Inject(PLATFORM_ID) private platformId: Object,
    @Inject(DOCUMENT) private document: Document
  ) {
    if (isPlatformBrowser(this.platformId)) {
      // 通过document.defaultView获取window对象
      this.ScrollWatcher = fromEvent(this.document.defaultView!, 'scroll');
    }
  }
}

额外注意事项

  • 如果ScrollWatcher在模板中使用async管道,需添加环境判断避免SSR报错,比如用*ngIf="isPlatformBrowser(platformId)"包裹相关模板元素,或者初始化一个空的Observable(new Observable())作为默认值。
  • 禁止在类的属性初始化阶段直接访问window,因为类初始化逻辑会在SSR过程中执行,此时window尚未存在。

内容的提问来源于stack exchange,提问作者Optiq

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 13:42:15