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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 21:25:37