谷歌身份-登录与谷歌按钮不可见时,去其他屏幕和回归



我正在尝试使用Google Identity API为Angular 14应用程序集成Google SSO。

我面临的问题是,当我第一次进入登录屏幕时,我可以看到登录与谷歌按钮。但如果我去其他屏幕,然后注销,当我回到登录屏幕,登录与谷歌按钮不再可见,我不得不强制刷新(Ctrl+Shift+R),使其可见。

我已经经历了为什么登录与谷歌按钮消失后,我渲染它第二次?但如何使我的情况可行还不清楚。

因为我可以看到Iframe将在第一次渲染,如果我从其他页面再次回到登录页面,我看不到Iframe和SignIn按钮不可见。

下面是从angular组件 加载登录按钮的代码
ngOnInit() {
// @ts-ignore
window.onGoogleLibraryLoad = () => {
// @ts-ignore
window.google.accounts.id.disableAutoSelect();
};
this.loadGoogleSSOScript('2.apps.googleusercontent.com');
}
loadGoogleSSOScript(clientId: string) {
// @ts-ignore
window.onGoogleLibraryLoad = () => {
// @ts-ignore
google.accounts.id.initialize({
client_id: clientId,
itp_support: true,
callback: this.handleCallback.bind(this),
});
// @ts-ignore
google.accounts.id.renderButton(
// @ts-ignore
document.getElementById('g_id_onload'),
{ theme: 'filled_blue', size: 'medium', width: '200px' }
);
// @ts-ignore
google.accounts.id.prompt(); // also display the  dialog
};
}

这里是Stackblitz的链接,它有完整的代码。

如何解决这个问题?

我解决这个问题的方法是将按钮移动到dom的另一个位置,而不是让它在我的组件被销毁时被销毁。

当我再次需要按钮时,我再次移动它。我使用"display:none"当我将按钮存储在dom的另一个位置时。

下面是一个移动按钮的例子:

// to be called in onDestroy method of component that renders google button
storeButton() {
const con = this.document.getElementById(this.storageConID);
const btn = this.document.getElementById(this.googleButtonID);
con!.insertBefore(btn as any, con?.firstChild || null);
} 

然而,我发现尝试在不同位置之间移动按钮的速度太快,连续多次呼叫el。insertBefore实际上会由于某种原因导致按钮完全从dom中消失。

在我的例子中,我正在登录页面和注册页面之间导航,两者都需要显示按钮。为了解决这个问题,我使用了MutationObserver并确保我没有试图将按钮移出它的"存储"直到它真的在那里。

我把它添加到我的index.html中,作为不应该显示按钮时存储按钮的地方。

<div id="google-btn-storage-con">
<div id="google-btn" class="flex-row justify-center items-center hidden"></div>
</div>

id为"google-btn"是我传递给google.accounts.id.renderButton方法的元素,用于在页面上初始呈现按钮。

当我需要显示google按钮时,我用id "google-btn"移动div到我的组件。

我希望这一点代码和解释是足够的。我想分享更多,但所有这些的实际实现有数百行长(包括使用MutationObserver和动态加载gsi脚本)。

在Angular中,你不应该直接访问DOM来获取元素,你可以使用ViewChild。

//HTML
<div #gbutton></div> 
//TS
export class LoginComponent implements OnInit, AfterViewInit {
@ViewChild('gbutton') gbutton: ElementRef = new ElementRef({});

constructor() { }

ngAfterViewInit() {
google.accounts.id.initialize({
client_id: clientId,
itp_support: true,
callback: this.handleCallback.bind(this),
});

google.accounts.id.renderButton(
this.gbutton.nativeElement,
{
type: "standard", theme: "outline",
size: "medium", width: "50", shape: "pill", ux_mode: "popup",
}
)
}

相关内容