问题
我正在尝试按照官方 Google 文档,使用 Vue Router 在我的 Vue 3 应用程序中创建 Google Sign In OAuth 按钮:https://developers.google.com/identity/gsi/web/guides/display-button
我完成了设置,完成了 OAuth 同意屏幕,获取了我的 CLIENT_ID,获得了用于回调的登录 uri,将其导入到 Vue 公共文件夹中的 index.html 文件中。
由于某种原因,该按钮未在我的 Vue Router 视图中呈现。
应用架构
Vue 3、组合 API、Vue 路由器
代码
GoogleAuthSignIn.vue 组件在我的 Vue 模板中显示按钮。我的 CLIENT_ID 当然是来自我的 API 的实际 ID
<template>
<div id="g_id_onload"
data-client_id="xxxxxx-xxxxxxxxxxxxxxxx.apps.googleusercontent.com"
data-context="signin"
data-ux_mode="popup"
data-login_uri="https://localhost:3000/api/auth/oauth/google"
data-itp_support="true">
</div>
<div class="g_id_signin"
data-type="standard"
data-shape="rectangular"
data-theme="outline"
data-text="signin_with"
data-size="large"
data-logo_alignment="left">
</div>
</template>
我还在“public”文件夹内的index.html 的头部添加了以下内容:
<script src="https://accounts.google.com/gsi/client" async defer></script>
奇怪的行为
我注意到有时很少它会突然加载,但我不知道为什么。例如,我可以刷新页面 50 次,其中一次有时会显示。
我读到这可能是脚本未加载的计时问题,或者脚本需要在按钮之前加载,或者按钮需要在脚本之前加载。我很困惑为什么会发生这种情况。
更新1
经过更多修改后,我意识到如果我将 HTML 渲染代码直接放在 App.vue 文件中,我可以显示/渲染按钮。
当我创建一个具有 g_id_onload 和 g_id_signin div 的组件并将该组件导入 App.vue 时,它也可以工作。
但是,它在通过 Vue 路由器加载的 SignUpView.vue 中不起作用。
*这是与Vue Router不兼容的问题吗?
更新2
我尝试复制该问题,发现在 Vue 路由器视图中加载 Google 登录按钮时出现问题。
解决方案
在 Vue Router index.js 文件顶部导入视图
import SignUpView from '../views/SignUpView.vue'
使用普通视图导入并像这样编写你的路线:
{
path: '/',
name: 'signUpView',
component: SignUpView
}
错误
不要使用代码分割的方式来编写你的路线:
{
path: '/',
name: 'landing',
component: () => import ('../views/SignUpView.vue')
}
为什么
当访问路由时,路由级代码分割是延迟加载的。 这意味着渲染视图时并非所有资源都会加载,只有在需要时才会加载资源。
根据我的理解,这会导致在公共文件夹的index.html文件中加载Google GSI脚本时出现问题:
<script src="https://accounts.google.com/gsi/client" async defer></script>
如果问题有另一种方法或更好的解释,请随时添加,因为我也很好奇是否有另一种可能的解决方案结合了延迟加载和加载谷歌脚本。
这就是我解决这个问题的方法,用组件一替换脚本标签。您可以将此代码直接用作 Vue 组件。
请参阅此处接受的答案。
<template>
<div class="login-provider-google">
<component :is="'script'" src="https://accounts.google.com/gsi/client" async />
<div id="g_id_onload"
data-client_id="..."
data-context="signin"
data-ux_mode="popup"
data-login_uri="..."
data-itp_support="true">
</div>
<div class="g_id_signin"
data-type="standard"
data-shape="rectangular"
data-theme="outline"
data-text="signin_with"
data-size="large"
data-logo_alignment="left">
</div>
</div>
</template>