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

Pinia中使用inject注入$zo实例返回undefined问题求助

Pinia Store中inject获取$zo实例返回undefined的原因及解决办法

我在使用vue-zo实现权限控制功能时,遇到一个问题:在Pinia的store中使用inject("$zo")返回undefined,但在App.vue中直接注入却能正常工作。

相关代码

GatesStore代码:

import { inject } from 'vue'
import { defineStore } from "pinia";

export const useGatesStore = defineStore("api", () => {
  const $zo = inject("$zo");
  
  const setRoles = () => {
    console.log($zo)
  }

  return {
    setRoles
  };
})

Main.js代码:

import './assets/base.scss'
import 'bootstrap/dist/css/bootstrap.css'
import 'nprogress/nprogress.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'

import { BootstrapVue } from 'bootstrap-vue'
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import { createPinia } from 'pinia'
import { createApp, markRaw } from 'vue'
import { router } from './router'
import { VueClipboard } from '@soerenmartius/vue3-clipboard'
import { VueZo } from 'vue-zo'

import Modal from "vue-bs-modal";
import progressBar from './includes/progress-bar';
import App from './App.vue'
import i18n from './includes/i18n'

import 'notyf/notyf.min.css';

import { useAuthStore } from '@/stores';

const pinia = createPinia();
pinia.use(({ store }) => { store.router = markRaw(router) });

const app = createApp(App)

app.config.errorHandler = () => null;
app.config.warnHandler = () => null;

app.use(pinia)

const authStore = useAuthStore();
authStore.attempt(localStorage.getItem('token')).then(() => 
{
    app.use(router)
    .use(i18n)
    .use(BootstrapVue)
    .use(Modal)
    .use(VueClipboard)
    .use(VueZo)
    .component("font-awesome-icon", FontAwesomeIcon)
    .mount('#app')
    progressBar(router)
})

问题原因

核心问题出在代码执行顺序上:

  1. 你先执行了app.use(pinia),紧接着就实例化了useAuthStore()并调用异步方法attempt
  2. 在异步回调执行之前,Pinia的所有store(包括useGatesStore)已经完成初始化,而此时VueZo插件还未安装,$zo并没有被注入到应用的全局依赖容器中
  3. App.vue能正常获取$zo,是因为组件渲染发生在app.mount('#app')之后——此时VueZo已经完成安装,依赖容器中已经存在$zo实例

解决方案

方案一:提前安装VueZo(优先推荐)

如果VueZo的安装不依赖auth验证结果,可以把app.use(VueZo)移到authStore调用之前,保证store初始化时$zo已存在:

const app = createApp(App)
app.config.errorHandler = () => null;
app.config.warnHandler = () => null;

app.use(pinia)
.use(VueZo) // 提前安装VueZo,保证依赖容器中存在$zo

const authStore = useAuthStore();
authStore.attempt(localStorage.getItem('token')).then(() => 
{
    app.use(router)
    .use(i18n)
    .use(BootstrapVue)
    .use(Modal)
    .use(VueClipboard)
    .component("font-awesome-icon", FontAwesomeIcon)
    .mount('#app')
    progressBar(router)
})

方案二:在方法内延迟获取$zo(适合必须在auth后安装VueZo的场景)

不在store的setup函数顶部直接inject,而是在需要使用的方法中获取,或通过当前实例访问全局属性:

import { inject, getCurrentInstance } from 'vue'
import { defineStore } from "pinia";

export const useGatesStore = defineStore("api", () => {
  let $zo = inject("$zo");
  
  const setRoles = () => {
    // 如果初始inject未获取到,从当前实例的全局属性中取
    if (!$zo) {
      const instance = getCurrentInstance();
      $zo = instance?.appContext.config.globalProperties.$zo;
    }
    console.log($zo)
  }

  return {
    setRoles
  };
})

方案三:通过Pinia插件注入$zo

在Pinia初始化时添加插件,将$zo直接注入到所有store实例中:

const pinia = createPinia();
pinia.use(({ store }) => { 
  store.router = markRaw(router);
  // 确保这段代码在app.use(VueZo)之后执行
  store.$zo = app.config.globalProperties.$zo;
});

// 先安装VueZo,再挂载Pinia
app.use(VueZo)
.use(pinia)

内容的提问来源于stack exchange,提问作者Bryan van der Starre

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 16:46:28