Pinia store 依靠 pinia
實例在所有調(diào)用中共享同一個 store 實例。大多數(shù)時候,只需調(diào)用你定義的 useStore()
函數(shù),完全開箱即用。例如,在 setup()
中,你不需要再做任何事情。但在組件之外,情況就有點不同了。
實際上,useStore()
給你的 app
自動注入了 pinia
實例。這意味著,如果 pinia
實例不能自動注入,你必須手動提供給 useStore()
函數(shù)。
你可以根據(jù)不同的應(yīng)用,以不同的方式解決這個問題。
如果你不做任何 SSR(服務(wù)器端渲染),在用 app.use(pinia)
安裝 pinia 插件后,對 useStore()
的任何調(diào)用都會正常執(zhí)行:
import { useUserStore } from '@/stores/user'
import { createApp } from 'vue'
import App from './App.vue'
// ? 失敗,因為它是在創(chuàng)建 pinia 之前被調(diào)用的
const userStore = useUserStore()
const pinia = createPinia()
const app = createApp(App)
app.use(pinia)
// ? 成功,因為 pinia 實例現(xiàn)在激活了
const userStore = useUserStore()
為確保 pinia 實例被激活,最簡單的方法就是將 useStore()
的調(diào)用放在 pinia 安
裝后才會執(zhí)行的函數(shù)中。
讓我們來看看這個在 Vue Router 的導(dǎo)航守衛(wèi)中使用 store 的例子。
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) => {
// ? 這樣做是可行的,因為路由器是在其被安裝之后開始導(dǎo)航的,
// 而此時 Pinia 也已經(jīng)被安裝。
const store = useStore()
if (to.meta.requiresAuth && !store.isLoggedIn) return '/login'
})
當處理服務(wù)端渲染時,你將必須把 pinia
實例傳遞給 useStore()
。這可以防止 pinia 在不同的應(yīng)用實例之間共享全局狀態(tài)。
在SSR 指南中有一整節(jié)專門討論這個問題,這里只是一個簡短的解釋。
更多建議: