Google OAuth登录按钮在使用Vue 3和Vue Router时未呈现。

huangapple go评论62阅读模式
英文:

Google OAuth Sign In button does not render in Vue 3 using Vue Router

问题

问题

我尝试在我的Vue 3应用中使用Vue Router创建一个Google Sign In OAuth按钮,按照官方的Google文档:https://developers.google.com/identity/gsi/web/guides/display-button

我完成了设置,完成了OAuth Consent Screen,获得了我的CLIENT_ID,有了用于回调的登录URI,在Vue的公共文件夹中的index.html文件中导入了

出于某种原因,按钮在我的Vue Router视图中不会渲染。

应用架构

Vue 3,Composition API,Vue Router

  • GoogleAuthSignIn.vue是一个组件
  • SignUpView.vue是一个视图(由Vue Router加载),导入并加载GoogleAuthSignIn.vue组件

代码

GoogleAuthSignIn.vue组件在我的Vue模板中显示按钮。我的CLIENT_ID当然是来自我的API的实际CLIENT_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_onloadg_id_signin div的组件,并将该组件导入到App.vue中时,它也有效。

但是,当我尝试加载通过Vue Router加载的SignUpView.vue时,它不起作用。

这是一个不兼容Vue Router的问题吗?

更新2

我尝试复制这个问题,发现在Vue Router视图中加载Google Sign In按钮存在问题。

  • 直接加载在App.vue中时,Google Sign In按钮会渲染
  • 当加载到一个视图中,然后加载到App.vue中时,Google Sign In按钮不会渲染
英文:

Problem

I'm trying to create a Google Sign In OAuth button in my Vue 3 app with Vue Router by following the official Google Docs: https://developers.google.com/identity/gsi/web/guides/display-button

I completed the setup, finished the OAuth Consent Screen, obtained my CLIENT_ID, have my login uri for the callback, imported the <scripts> in my index.html file in Vue public folder.

For some reason, the button does not render in my Vue Router Views.

App Architecture

Vue 3, Composition API, Vue Router

  • GoogleAuthSignIn.vue is a component
  • SignUpView.vue is a view (Loaded by Vue Router) that imports and loads the GoogleAuthSignIn.vue component

Code

GoogleAuthSignIn.vue component displaying the button inside my Vue template. My CLIENT_ID is of course the actual one from my API

&lt;template&gt;
    &lt;div id=&quot;g_id_onload&quot;
        data-client_id=&quot;xxxxxx-xxxxxxxxxxxxxxxx.apps.googleusercontent.com&quot;
        data-context=&quot;signin&quot;
        data-ux_mode=&quot;popup&quot;
        data-login_uri=&quot;https://localhost:3000/api/auth/oauth/google&quot;
        data-itp_support=&quot;true&quot;&gt;
    &lt;/div&gt;

    &lt;div class=&quot;g_id_signin&quot;
        data-type=&quot;standard&quot;
        data-shape=&quot;rectangular&quot;
        data-theme=&quot;outline&quot;
        data-text=&quot;signin_with&quot;
        data-size=&quot;large&quot;
        data-logo_alignment=&quot;left&quot;&gt;
    &lt;/div&gt;
&lt;/template&gt;

I've also included the following inside the head of the index.html inside the "public" folder:

&lt;script src=&quot;https://accounts.google.com/gsi/client&quot; async defer&gt;&lt;/script&gt;

Strange Behavior

I notice that sometimes very rarely it suddenly loads but I have no idea why. For example, I can refresh the page 50 times, and one of those times it will sometimes show.

I was reading this might be a timing issue of the script not loading, or that the script needs to load before the button, or button needs to load before the script. I am pretty confused as to why this happens.

Update 1

After tinkering some more, I realized that I can show / render the button if I place the HTML render code directly inside the App.vue file.

It also works when I create a component that has the g_id_onload and g_id_signin divs, and import that component into App.vue.

However, it doesn't work inside my SignUpView.vue that loads via the Vue Router.

*Is this an issue where it is not compatible with Vue Router?

Update 2

I tried replicating the issue and found out that there is a problem with loading the Google Sign In Buttons inside of Vue Router Views.

  • Google Sign In buttons render when loaded directly in App.vue
  • Google Sign In buttons do NOT render when loaded into a View, which is then loaded into App.vue

答案1

得分: 0

解决方案

在你的Vue Router的index.js文件顶部导入你的视图:

import SignUpView from '../views/SignUpView.vue'

使用正常的视图导入方式,并编写你的路由如下:

{
    path: '/',
    name: 'signUpView',
    component: SignUpView
}

错误

不要使用代码分割的方式来编写你的路由:

{
    path: '/',
    name: 'landing',
    component: () => import('../views/SignUpView.vue')
}

为什么

路由级别的代码分割在访问路由时才进行延迟加载。
这意味着在渲染视图时不会加载所有资源,资源只在需要时加载。

根据我的理解,这会导致在public文件夹的index.html文件中加载Google GSI脚本时出现问题:

<script src="https://accounts.google.com/gsi/client" async defer></script>

如果有其他方法或更好的解释问题的方式,请随时添加,因为我也很想知道是否有结合延迟加载和加载Google脚本的其他可能解决方案。

英文:

Solution

Import your view at the top of your Vue Router index.js file

import SignUpView from &#39;../views/SignUpView.vue&#39;

Use normal view imports and write your route like this:

{
    path: &#39;/&#39;,
    name: &#39;signUpView&#39;,
    component: SignUpView
}

Error

Do Not Use the Code-Splitting way of writing your route:

{
    path: &#39;/&#39;,
    name: &#39;landing&#39;,
    component: () =&gt; import (&#39;../views/SignUpView.vue&#39;)
}

Why

Route level code-splitting is lazy-loaded when the route is visited.
This means that not all resources are loaded when the view is rendered, and resources are loaded only when they are needed.

From my understanding, this causes an issue with loading the Google GSI Script in the index.html file in the public folder:

&lt;script src=&quot;https://accounts.google.com/gsi/client&quot; async defer&gt;&lt;/script&gt;

If there is another way or better explanation of the issue feel free to add one as I would also be curious if there is another possible solution that combines lazy-loading and loading the google scripts.

huangapple
  • 本文由 发表于 2023年6月5日 17:56:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76405268.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定