Angular中添加多个Google登录按钮时出现控制台错误
问题分析
你遇到的Cannot read properties of undefined (reading 'pb')错误,是Google GSI库在重复渲染按钮或组件状态管理不当导致的内部状态冲突,虽然功能正常,但这类错误通常源于:
- 组件多次创建/销毁时,Google按钮实例未被正确清理
- 多组件实例共享初始化逻辑时,元素渲染时机与库内部状态不同步
- 重复向同一元素渲染按钮,引发库内部的DOM引用错误
解决方案
1. 渲染按钮前清空目标元素
每次调用renderButton前,先清空按钮容器的内容,避免重复渲染同一元素引发的冲突:
ngAfterViewInit(): void { // 初始化逻辑保留(如果仍在组件中处理) if (!this.isGoogleInited) { google.accounts.id.initialize({ client_id: 'my-client-id.apps.googleusercontent.com', callback: (response: any) => this.handleGoogleSignIn(response), }); this.isGoogleInited = true; } // 渲染前清空元素,清除旧的按钮实例 this.googleBtn.nativeElement.innerHTML = ''; // 渲染新按钮 google.accounts.id.renderButton( this.googleBtn.nativeElement, { size: 'large', type: 'standard', shape: 'pill', width: 400, text: 'signin_with', locale: 'en_US', logo_alignment: 'left' }, ); }
2. 组件销毁时清理按钮实例
在组件的ngOnDestroy钩子中清空按钮容器,避免库继续引用已被移除的DOM元素:
ngOnDestroy(): void { if (this.googleBtn?.nativeElement) { this.googleBtn.nativeElement.innerHTML = ''; } }
3. 全局初始化GSI库(推荐)
将GSI初始化逻辑移到应用启动阶段,避免组件级的状态判断,确保整个应用只初始化一次:
在app.module.ts中配置全局初始化
import { NgModule, APP_INITIALIZER } from '@angular/core'; import { AuthService } from './auth.service'; // 假设你有处理登录的服务 export function initializeGoogleAuth(authService: AuthService) { return () => new Promise<void>((resolve) => { // 轮询等待GSI脚本加载完成 const loadCheck = setInterval(() => { if (typeof google !== 'undefined' && google.accounts?.id) { clearInterval(loadCheck); google.accounts.id.initialize({ client_id: 'my-client-id.apps.googleusercontent.com', callback: (response) => authService.handleGoogleSignIn(response) }); resolve(); } }, 100); }); } @NgModule({ providers: [ AuthService, { provide: APP_INITIALIZER, useFactory: initializeGoogleAuth, deps: [AuthService], multi: true } ] }) export class AppModule { }
组件中仅负责渲染按钮
ngAfterViewInit(): void { this.googleBtn.nativeElement.innerHTML = ''; google.accounts.id.renderButton( this.googleBtn.nativeElement, { size: 'large', type: 'standard', shape: 'pill', width: 400, text: 'signin_with', locale: 'en_US', logo_alignment: 'left' }, ); } ngOnDestroy(): void { if (this.googleBtn?.nativeElement) { this.googleBtn.nativeElement.innerHTML = ''; } }
4. 确保GSI脚本加载完成后再执行逻辑
如果脚本加载延迟导致google对象未定义,可在组件中添加加载检查:
ngAfterViewInit(): void { const initAndRender = () => { if (typeof google === 'undefined' || !google.accounts?.id) { setTimeout(initAndRender, 100); return; } // 初始化(如果用全局初始化可跳过) if (!this.isGoogleInited) { google.accounts.id.initialize({/*配置*/}); this.isGoogleInited = true; } this.googleBtn.nativeElement.innerHTML = ''; google.accounts.id.renderButton(/*参数*/); }; initAndRender(); }
关于获取未压缩GSI库
你可以直接访问控制台中sourceURL的完整地址,去掉参数中的压缩标识(如am=6g),即可获取未压缩的调试版本,方便排查内部逻辑。
内容的提问来源于stack exchange,提问作者Vladyslav Yermolin
相关产品推荐
相关产品推荐

