使用angular-code-input组件触发document未定义ReferenceError错误求助
使用angular-code-input库时出现document未定义错误
我在使用angular-code-input库时,加载包含该组件的页面遇到错误,错误信息如下:
- Changes detected. Rebuilding... ERROR ReferenceError: document is not defined at _CodeInputComponent.focusOnInputAfterAppearing (c:/Users/X/Documents/sourcecode/web/node_modules/angular-code-input/fesm2022/angular-code-input.mjs:300:52) at _CodeInputComponent.ngAfterViewChecked (c:/Users/X/Documents/sourcecode/web/node_modules/angular-code-input/fesm2022/angular-code-input.mjs:103:10) at callHookInternal (c:/Users/X/Documents/sourcecode/web/node_modules/@angular/core/fesm2022/core.mjs:6117:14) at callHook (c:/Users/X/Documents/sourcecode/web/node_modules/@angular/core/fesm2022/core.mjs:6148:9) at callHooks (c:/Users/X/Documents/sourcecode/web/node_modules/@angular/core/fesm2022/core.mjs:6099:17) at executeInitAndCheckHooks (c:/Users/X/Documents/sourcecode/web/node_modules/@angular/core/fesm2022/core.mjs:6049:9) at refreshView (c:/Users/X/Documents/sourcecode/web/node_modules/@angular/core/fesm2022/core.mjs:12171:21) at detectChangesInView (c:/Users/X/Documents/sourcecode/web/node_modules/@angular/core/fesm2022/core.mjs:12324:9) at detectChangesInViewIfAttached (c:/Users/X/Documents/sourcecode/web/node_modules/@angular/core/fesm2022/core.mjs:12287:5) at detectChangesInEmbeddedViews (c:/Users/X/Documents/sourcecode/web/node_modules/@angular/core/fesm2022/core.mjs:12244:13) ERROR ReferenceError: document is not defined at _CodeInputComponent.focusOnInputAfterAppearing (c:/Users/X/Documents/sourcecode/web/node_modules/angular-code-input/fesm2022/angular-code-input.mjs:300:52) at _CodeInputComponent.ngAfterViewChecked (c:/Users/X/Documents/sourcecode/web/node_modules/angular-code-input/fesm2022/angular-code-input.mjs:103:10) at callHookInternal (c:/Users/X/Documents/sourcecode/web2/node_modules/@angular/core/fesm2022/core.mjs:6117:14) at callHook (c:/Users/X/Documents/sourcecode/web/node_modules/@angular/core/fesm2022/core.mjs:6148:9) at callHooks (c:/Users/X/Documents/sourcecode/web/node_modules/@angular/core/fesm2022/core.mjs:6099:17) at executeInitAndCheckHooks (c:/Users/X/Documents/sourcecode/web/node_modules/@angular/core/fesm2022/core.mjs:6049:9) at refreshView (c:/Users/X/Documents/sourcecode/web/node_modules/@angular/core/fesm2022/core.mjs:12171:21) at detectChangesInView (c:/Users/X/Documents/sourcecode/web/node_modules/@angular/core/fesm2022/core.mjs:12324:9) at detectChangesInViewIfAttached (c:/Users/X/Documents/sourcecode/web/node_modules/@angular/core/fesm2022/core.mjs:12287:5)
问题细节
错误源于Angular Code Input组件,与document对象的使用有关,导航到包含该组件的路由时document不可用。
复现步骤
- 启动Angular项目
- 导航到使用Angular Code Input组件的路由,组件加载但终端报错
预期行为
导航后组件无错误加载完成
环境信息
- Angular版本:17.1.0
- 操作系统:Windows
- Node.js版本:v18.19.1
- npm版本:10.2.4
解决方案
这个错误是因为angular-code-input库直接访问了document对象,而在Angular 17的服务器端渲染(SSR)或预渲染场景下,服务器环境中不存在document对象,导致报错。可以通过以下几种方式解决:
1. 关闭SSR/预渲染(如果不需要)
若项目不需要SSR或预渲染,修改angular.json配置:
- 将
architect.build.options.ssr设为false - 移除
prerender相关配置项
2. 封装document访问逻辑
创建Angular服务封装对document的访问,确保仅在浏览器环境执行:
import { Injectable, Inject, PLATFORM_ID } from '@angular/core'; import { isPlatformBrowser } from '@angular/common'; @Injectable({ providedIn: 'root' }) export class DocumentService { constructor(@Inject(PLATFORM_ID) private platformId: Object) {} get document(): Document | null { return isPlatformBrowser(this.platformId) ? window.document : null; } }
之后可以封装angular-code-input组件,在执行涉及document的逻辑前先判断环境:
import { Component, Inject, PLATFORM_ID } from '@angular/core'; import { isPlatformBrowser } from '@angular/common'; @Component({ selector: 'app-code-input-wrapper', template: `<angular-code-input [length]="6"></angular-code-input>` }) export class CodeInputWrapperComponent { constructor(@Inject(PLATFORM_ID) private platformId: Object) {} ngAfterViewChecked() { if (!isPlatformBrowser(this.platformId)) return; // 按需调整组件focus逻辑,或覆盖原组件相关方法 } }
3. 条件渲染组件
仅在浏览器环境下渲染angular-code-input:
<ng-container *ngIf="isBrowser"> <angular-code-input [length]="6"></angular-code-input> </ng-container>
组件类中添加环境判断:
import { Component, Inject, PLATFORM_ID } from '@angular/core'; import { isPlatformBrowser } from '@angular/common'; @Component({ selector: 'app-your-component', templateUrl: './your-component.component.html' }) export class YourComponent { isBrowser: boolean; constructor(@Inject(PLATFORM_ID) private platformId: Object) { this.isBrowser = isPlatformBrowser(this.platformId); } }
4. 反馈问题或更换组件
如果上述方案不适用,可在该库的代码仓库提交issue要求修复SSR兼容性;或选择支持SSR的验证码输入组件替代。
内容的提问来源于stack exchange,提问作者Philip Mutua
相关产品推荐
相关产品推荐

