Vue3中如何让main.ts先执行再渲染组件?Keycloak初始化问题
解决Vue3中Keycloak初始化滞后导致组件无法获取Pinia Token的问题
问题原因
你当前的代码中,keycloak.init()是异步Promise操作,但app.mount('#app')是同步执行的——这意味着Vue会先渲染组件,再完成Keycloak的初始化和Pinia的Token赋值,所以NavigationBar组件的mounted钩子会先触发,此时Pinia里的storedToken还是空值。
核心解决方案:等待Keycloak初始化完成后再挂载应用
将应用挂载操作放到Keycloak初始化完成的回调中,确保所有鉴权逻辑执行完毕后,再开始渲染组件。
修改后的main.ts代码
import { createApp } from 'vue' import './style.css' import Keycloak from "keycloak-js"; import { createPinia } from 'pinia' import {useAuthStore} from "./store/auth"; // @ts-ignore import App from './App.vue' const pinia = createPinia() const app = createApp(App); app.use(pinia); let keycloak = new Keycloak({ url: "http://192.168.0.2:8082/", realm: "test", clientId: "test" }); // 用async/await处理异步初始化,确保完成后再挂载 (async () => { try { await keycloak.init({ redirectUri: "http://localhost:5173", onLoad: "check-sso", checkLoginIframe: false, // @ts-ignore token: localStorage.getItem("token"), // @ts-ignore refreshToken: localStorage.getItem("refreshToken") }); const authStore = useAuthStore(); authStore.storedToken = keycloak.token as string; console.log("main.ts check authStore, storedToken: " + keycloak.token); if (keycloak?.authenticated) { keycloak.token && localStorage.setItem("token", keycloak.token); keycloak.refreshToken && localStorage.setItem("refreshToken", keycloak.refreshToken); } console.log(keycloak); // 所有初始化完成后再挂载应用 app.mount('#app'); } catch (error) { console.error("Keycloak初始化失败", error); // 初始化失败的兜底处理,比如直接挂载或跳转到登录页 app.mount('#app'); } })(); export default keycloak;
额外优化:让组件响应Token变化
即使等待初始化后挂载,后续Token刷新时,组件也需要同步更新。可以在NavigationBar组件中用computed或watch监听Pinia的Token:
修改后的NavigationBar.vue代码
<script lang="ts"> import keycloak from "../main"; import {useAuthStore} from "../store/auth"; import {computed} from 'vue'; export default { name: "NavigationBar", setup() { const authStore = useAuthStore(); // 用computed响应式获取Token,自动同步变化 const userToken = computed(() => authStore.storedToken); console.log("authStore.storedToken " + authStore.storedToken); return { userToken, keycloak }; }, methods: { keycloak() { return keycloak } } } </script>
可选优化:Pinia Store预加载LocalStorage的Token
可以在Pinia的authStore中直接从LocalStorage读取Token,减少对Keycloak回调的依赖,让Store初始化就有值:
// store/auth.ts import { defineStore } from 'pinia' export const useAuthStore = defineStore('auth', { state: () => ({ storedToken: localStorage.getItem("token") || "" }), actions: { setToken(token: string) { this.storedToken = token; localStorage.setItem("token", token); } } })
这样即使Keycloak初始化有延迟,Store里也会先有LocalStorage的Token值,组件能更早获取到。
内容的提问来源于stack exchange,提问作者Decrux
相关产品推荐
相关产品推荐

