You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 17:32:18