引言
大家应该都知道,Pinia 是 Vue 3 推荐的状态管理插件,而不再是 Vuex。而习惯使用Vuex的你,一定不习惯在开发中无法通过一个全局变量 $store
访问,并且无法在任何地方轻松访问它!
因此,我们今天给大家介绍一种方法,让你在使用 Pinia 时也可以像使用Vuex一样顺畅!
首先了解一下Pinia缺失的三个基本功能:
- 1. 使用我们熟悉的
this.$store
访问 store - 2. 有一个嵌套结构的 store
- 3. 在 Actions 中访问 Vue Router
基本设置
我们在 src/store
目录下创建了所有的 store,目录结构如下:
- src -> store -> auth -> getters.js -> index.js -> state.js -> index.js -> state.js
主要的 index.js
充当完整 store 的入口点,关于嵌套和其他内容的工作原理,我们将在第二步中解释。
// src/store/index.js import state from "./state.js" import authStore from "./auth" export const useStore = defineStore('core', { state: () => state, actions: { setStores() { this.auth = authStore() } } }) export default useStore // src/store/state.js export default { auth: null, version: "1.0.0", } // src/store/auth/index.js import state from "./state.js" import getters from "./getters.js" export const useStore = defineStore('auth', { state: () => state, getters, actions: { updateUserToken (token) { this.token = token localStorage.setItem('token', token) } }) export default useStore // src/store/auth/state.js export default { token: null } // src/store/auth/getters.js export default {}
在 Pinia 中嵌套存储
Pinia 本质上是为了直接在需要时导入和使用 store,但这不是我们想要的,我们希望像在 Vuex 中那样方便地访问,因此我们做了以下操作:
- • 在主 store 中创建一个名为 store 的新状态变量,例如
auth
// src/store/state.js export default { auth: null }
- • 在主 store 中初始化并设置为想要使用的 Pinia store,例如
authStore
,将其添加到我们可以初始化所有需要的 store 的主 store 中的一个 action 中,例如setStores()
// src/store/index.js ... import authStore from "./auth" ... export const useStore = defineStore('core', { state: () => state, actions: { setStores() { this.auth = authStore() // 在 action 中初始化 store }, ... // 其他方法 } })
- • 一旦初始化了主 store,就调用该 action
// main.js ... import { createPinia } from 'pinia' ... import store from "@/store" ... app.use(createPinia()) // 创建 Pinia export const $store = store() // 初始化主 store $store.setStores() // 调用 action 初始化所有嵌套 store
现在,所有 store 都可以直接从主 store 中访问,以下是一个示例(Options API):
<script> import { $store } from "@/main.js" export default { mounted() { console.log($store.auth.token) // 访问 auth 的状态 console.log($store.auth.updateUserToken("12345")) // 调用 auth 的 action console.log($store.someState) // 访问主 store 的状态 } } </script>
使 Pinia store 在全局可访问
既然我们的 store 已经嵌套并可以通过单个变量访问,现在是时候通过 vue 的全局属性将其直接访问到组件内部了。为此,我们将使用 vue 中的全局属性进行映射。操作如下:
- • 在
main.js
中初始化主 store
// main.js ... import { createPinia } from 'pinia' ... import store from "@/store" ... app.use(createPinia()) // 创建 Pinia export const $store = store() // 初始化主 store app.config.globalProperties.$store = $store // 使 store 在全局可访问 app.config.globalProperties.$store.setStores() // 调用 action 初始化所有嵌套 store
现在,您可以在组件内部(Options API)中访问它,如下所示:
<script> export default { mounted() { console.log(this.$store.auth.token) // 访问 auth 的状态 console.log(this.$store.auth.updateUserToken("12345")) // 调用 auth 的 action console.log(this.$store.someState) // 访问主 store 的状态 }, watch: { '$store.auth.token'() { console.log("Changed") } // 甚至可以监视它 } } </script>
在 Pinia Actions 中访问 Vue Router
我们尝试直接在 store 中导入 router 实例并使用它,但感觉不太对,这时我们找到了一个方法,我们可以像这样设置某些属性:
- • 在
main.js
中
// main.js ... import router from '@/router' ... import { createPinia } from 'pinia' let pinia = createPinia() pinia.use({store} => {store.router = router}) // 在此设置 router,以便在 store 中访问 app.use(pinia) ...
这样我们就可以随时在 store 中访问 router 实例了,如下所示:
// src/store/index.js ... import authStore from "./auth" ... export const useStore = define Store('core', { state: () => state, actions: { logRoute() { console.log(this.router) // Router 实例 console.log(this.router.currentRoute) // 获取当前路由 (this.$route) } ... // 其他方法 } })
通过这种方式,我们解决了我们的三大难题!下面是完整的代码,包含了所有三个功能的实现。
目录结构
- src -> store -> auth -> getters.js -> index.js -> state.js -> index.js -> state.js -> main.js -> router -> index.js
// src/store/index.js import state from "./state.js" import authStore from "./auth" export const useStore = defineStore('core', { state: () => state, actions: { setStores() { this.auth = authStore() } } }) export default useStore
// src/store/state.js export default { auth: null, version: "1.0.0", }
// src/store/auth/index.js import state from "./state.js" import getters from "./getters.js" export const useStore = defineStore('auth', { state: () => state, getters, actions: { updateUserToken (token) { this.token = token localStorage.setItem('token', token) } }) export default useStore
// src/store/auth/state.js export default { token: null } // src/store/auth/getters.js export default {}// src/store/auth/state.js export default { token: null } // src/store/auth/getters.js export default {}
// main.js ... import router from '@/router' ... import { createPinia } from 'pinia' let pinia = createPinia() pinia.use({store} => {store.router = router}) // 在此设置 router,以便在 store 中访问 app.use(pinia) ... export const $store = store() // 初始化主 store app.config.globalProperties.$store = $store // 使 store 在全局可访问 app.config.globalProperties.$store.setStores() // 调用 action 初始化所有嵌套 store
以上就是全部内容!如果您发现其他实现相同目标的方法,请告诉我们!