Vue3 SFC中Google登录回调函数handleCredentialResponse无法触发的问题
Vue3 SFC 中 Google 登录回调不触发的解决方案
问题核心:Google GSI API 会在全局 window 作用域查找你指定的回调函数,但 <script setup> 里定义的函数属于模块私有作用域,不会暴露到全局,因此 Google 无法找到并调用它。defineExpose 是给父 Vue 组件暴露内部方法用的,和全局作用域无关,所以无效。
具体解决步骤
1. 将回调函数挂载到 window 全局对象
把你的回调函数挂载到 window 上,让 Google API 能访问到:
<script setup lang="ts"> import { authStore } from '@/stores/authStore'; import { User } from '@/stores/authStore'; import { useRouter, onUnmounted } from 'vue'; const router = useRouter(); const auth = authStore() // 定义登录回调函数 function handleCredentialResponse(googleUser: any) { fetch(`https://localhost:7237/myApi/ValidateToken?token=${googleUser.credential}`, { method: "GET", }) .then(response => response.json()) .then(data => { auth.user = new User("Mr Test", data.token); router.push(auth.returnUrl) }) } // 挂载到全局 window 对象(TypeScript 需类型断言) (window as any).handleCredentialResponse = handleCredentialResponse; // 组件卸载时清理全局变量,避免内存泄漏 onUnmounted(() => { delete (window as any).handleCredentialResponse; }) </script>
2. 优化 GSI 脚本加载方式(可选但推荐)
用 Vue 生命周期钩子动态加载脚本,比 <component :is="script"> 更可控,避免重复加载:
import { onMounted } from 'vue'; onMounted(() => { // 检查脚本是否已存在,防止重复插入 if (!document.querySelector('script[src="https://accounts.google.com/gsi/client"]')) { const script = document.createElement('script'); script.src = 'https://accounts.google.com/gsi/client'; script.async = true; script.defer = true; document.body.appendChild(script); } })
3. 模板代码保持不变
你的原有模板无需修改:
<template> <div id="g_id_onload" data-client_id="454813487606-q3gep6aurieacd3kj02upb6fcfh2sqqb" data-callback="handleCredentialResponse"> </div> <div class="g_id_signin" data-type="standard"></div> </template>
关键原因说明
<script setup>采用模块模式,内部所有变量、函数都是私有作用域,不会自动挂载到window,Google API 无法访问。defineExpose仅用于 Vue 组件树内部的父组件通过模板引用访问当前组件方法,和全局作用域无关联,无法解决全局回调问题。
内容的提问来源于stack exchange,提问作者Darren Rogers
相关产品推荐
相关产品推荐

