在Vue.js Web Components中使用Pinia时出现Symbol(pinia)注入未找到错误
在Vue Web Components中使用Pinia解决「injection 'Symbol(pinia)' not found」错误
你遇到的错误是因为Vue自定义元素(Web Components)是独立的Vue实例,没有像常规Vue应用那样全局挂载Pinia实例,导致组件无法通过依赖注入找到Pinia。
问题分析
你的store.ts中直接调用setActivePinia(createPinia())只会在模块加载时创建一次Pinia实例,但这个实例并没有关联到Web Components的Vue根实例上,因此组件无法获取到它。
解决方案
下面提供两种可行的修改方式:
方式一:在定义自定义元素时注入Pinia插件
修改main.ts,在定义自定义元素时通过plugins选项传入Pinia实例:
import { defineCustomElement } from 'vue' import HelloWorld from './components/HelloWorld.ce.vue' import { createPinia } from 'pinia' // 创建Pinia实例 const pinia = createPinia() // 定义自定义元素时传入Pinia插件 const ExampleElement = defineCustomElement(HelloWorld, { plugins: [pinia] }) customElements.define('hello-world', ExampleElement)
同时修改store.ts,移除不必要的setActivePinia调用:
import { defineStore } from "pinia"; export const useCounterStore = defineStore('counter', { state: () => ({ counter: 0, }), actions: { increment() { this.counter++; }, }, });
方式二:在组件内部创建并提供Pinia实例
如果需要每个组件实例拥有独立的Pinia存储,可以在组件的setup中创建并提供Pinia:
修改HelloWorld.ce.vue:
<script setup lang="ts"> import { provide } from 'vue' import { useCounterStore, createPinia } from '../store.ts' import { PiniaSymbol } from 'pinia' defineProps<{ msg: string }>() // 创建Pinia实例并提供给组件 const pinia = createPinia() provide(PiniaSymbol, pinia) // 使用Pinia实例初始化store const store = useCounterStore(pinia) </script> <template> <h1>{{ msg }}</h1> <div class="card"> <button type="button" @click="store.increment()">count is {{ store.counter }}</button> </div> </template>
同样需要修改store.ts移除setActivePinia调用,和方式一中的store.ts一致。
说明
两种方式的区别在于:
- 方式一让所有自定义元素实例共享同一个Pinia存储
- 方式二每个组件实例拥有独立的Pinia存储,适合需要隔离状态的场景
内容的提问来源于stack exchange,提问作者Amaury Hanser
相关产品推荐
相关产品推荐

