实际上,useStore()
给你的 app
自动注入了 pinia
实例。这意味着,如果 pinia
实例不能自动注入,你必须手动提供给 useStore()
函数。
你可以根据不同的应用,以不同的方式解决这个问题。
单页面应用
如果你不做任何 SSR(服务器端渲染),在用 app.use(pinia)
安装 pinia 插件后,对 useStore()
的任何调用都会正常执行:
js
import { createPinia } from 'pinia'
import { createApp } from 'vue'
import App from './App.vue'
import { useUserStore } from '@/stores/user'
// ❌ 失败,因为它是在创建 pinia 之前被调用的
const userStore1 = useUserStore()
const pinia = createPinia()
const app = createApp(App)
app.use(pinia)
// ✅ 成功,因为 pinia 实例现在激活了
const userStore2 = useUserStore()
为确保 pinia 实例被激活,最简单的方法就是将 useStore()
的调用放在 pinia 安装后才会执行的函数中。
让我们来看看这个在 Vue Router 的导航守卫中使用 store 的例子。
js
import { createRouter } from 'vue-router'
const router = createRouter({
// ...
})
// ❌ 由于引入顺序的问题,这将失败
const store = useStore()
router.beforeEach((to, from, next) => {
// 我们想要在这里使用 store
if (store.isLoggedIn)
next()
else next('/login')
})
router.beforeEach((to) => {
// ✅ 这样做是可行的,因为路由器是在其被安装之后开始导航的,
// 而此时 Pinia 也已经被安装。
const store = useStore()
if (to.meta.requiresAuth && !store.isLoggedIn)
return '/login'
})
服务端渲染应用
当处理服务端渲染时,你将必须把 pinia
实例传递给 useStore()
。这可以防止 pinia 在不同的应用实例之间共享全局状态。
在SSR 指南中有一整节专门讨论这个问题,这里只是一个简短的解释。