Angular SSR中cdk-virtual-scroll-viewport的scrollWindow属性报错:document未定义
解决Angular SSR中cdk-virtual-scroll-viewport的scrollWindow属性报错问题
问题原因
在Angular SSR应用中使用cdk-virtual-scroll-viewport并设置scrollWindow属性时,服务端渲染阶段会触发document is not defined错误。这是因为scrollWindow模式直接依赖浏览器环境的window和document对象,而SSR服务端不存在这些对象。
解决方案:服务端/客户端条件渲染
通过Angular的isPlatformBrowser工具,在服务端渲染时跳过依赖浏览器环境的虚拟滚动组件,仅在客户端加载完成后再渲染该组件,同时为服务端提供简化的替代内容。
步骤1:修改组件逻辑
在app.component.ts中注入PLATFORM_ID,判断当前运行环境是否为浏览器:
import { ChangeDetectionStrategy, Component, Inject, PLATFORM_ID } from '@angular/core'; import { ScrollingModule } from '@angular/cdk/scrolling'; import { isPlatformBrowser } from '@angular/common'; @Component({ selector: 'app-root', styleUrl: './app.component.scss', templateUrl: './app.component.html', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [ScrollingModule] }) export class AppComponent { items = Array.from({length: 100000}).map((_, i) => `Item #${i}`); isBrowser: boolean; constructor(@Inject(PLATFORM_ID) platformId: Object) { this.isBrowser = isPlatformBrowser(platformId); } }
步骤2:修改模板实现条件渲染
在app.component.html中,根据环境判断结果渲染对应内容:
<div class="example-header">Content before</div> <!-- 客户端环境下渲染虚拟滚动组件 --> <ng-container *ngIf="isBrowser"> <cdk-virtual-scroll-viewport scrollWindow itemSize="50"> <div *cdkVirtualFor="let item of items" class="example-item">{{item}}</div> </cdk-virtual-scroll-viewport> </ng-container> <!-- 服务端渲染时显示简化列表,兼顾SEO和页面完整性 --> <div *ngIf="!isBrowser"> <div *ngFor="let item of items | slice:0:20" class="example-item">{{item}}</div> <div class="example-item">更多内容请在浏览器中查看</div> </div> <div class="example-footer">Content after</div>
补充说明
- 服务端渲染简化列表,既避免了服务端生成大量DOM节点影响性能,也保证了页面有可被搜索引擎抓取的内容。
- 客户端加载完成后,虚拟滚动组件会正常工作,保留原有的性能优化特性。
内容的提问来源于stack exchange,提问作者Sidharth Bajpai
相关产品推荐
相关产品推荐

