Vue使用Pinia轻松实现状态管理
作者:格斗家不爱在外太空沉思
前言
pinia,一个基于Vue3的状态管理库,它可以帮助开发人员管理Vue应用程序的状态,Pinia使用Vue3的Composition API提供了更简单,灵活的状态管理方式,通过创建store来管理应用程序的状态,还提供了插件和工具来帮助开发人员更轻松的使用它。
Pinia对比VueX
之前我们在vue2的时候使用的状态管理库是VueX,在Vue3中想使用VueX,需要使用到VueX4版本,而在Vue3组合式API下设计了全新的状态管理库:Vuex5,也就是Pinia(已经被纳入官方了)
那Pinia相比VueX有什么优势呢?
在当时pinia的作者就作出了这么一个提案:
- pinia都支持在vue2和vue3中使用
- 在vuex想修改数据状态需要mutations,而pinia去掉了mutations,只有state,getters和actions。修改数据状态直接在actions里操作,pinia推崇使用类似于 JavaScript 对象的方式来更新状态,即直接对 state 进行修改,可以减少代码量,并且降低了出错的可能性
- pinia中没有嵌套模块,在vuex中我们可能会用到大量的模块,一层套一层,使状态管理变得复杂,也有可能会造成命名冲突,在Composition API下pinia中可以定义多个store,然后将多个store组合在一起,变得更加灵活
- 完整的TypeScript支持,vuex对ts的类型检查,类型推断和泛型的支持都不太友好,模块命名空间的支持也不够完善
除此之外两者的api都是相同的,使用的方式也是相同的,关于vuex的使用可以看看之前写的vuex文章
Pinia的使用
安装pinia
使用pinia需要先安装,可以通过yarn或者npm安装
yarn add pinia
# or with npm
npm install pinia
在vue2中使用,你还需要安装一个插件并pinia
在应用程序的根目录注入创建的,如果vue版本<2.7,还需要安装 composition api: @vue/composition-api
安装完之后在入口文件引入pinia的createPinia方法并调用得到pinia的实例,然后挂载到vue实例上
import { createApp } from "vue"; import App from "./App.vue"; import { createPinia } from "pinia"; //创建pinia实例 const pinia = createPinia(); const app = createApp(App); //挂载到vue实例上 app.use(pinia); app.mount("#app");
定义store容器
在src目录下创建store目录来存放pinia容器相关代码,在里面新建了一个index.ts文件,在index.ts文件里首先要定义一个容器,定义容器使用defineStore
来定义,主要接收两个参数,一个是容器的名字(唯一),另一个是容器的对象,最后将容器导出,就可以在组件中使用了
import { defineStore } from "pinia"; export const useTestStore = defineStore("test", { /** * 类似组件中的data,存储全局状态 * 必须是箭头函数,避免数据状态污染 */ state: () => { return { message: "hello world", count:0, }; }, /** * 类似组件中的computed */ getters: {}, /** * 类似组件中的methods,封装业务逻辑,修改state */ actions: {}, });
在组件中导入并使用容器
state的使用
在组件中导入容器并且调用,得到容器的实例,就可以直接使用state里的数据或者在模板中展示
<script setup lang="ts"> import { useTestStore } from "./store"; const store = useTestStore(); </script> <template> <div>{{ store.message }}</div> </template> <style scoped> </style>
也可以使用解构
的方式拿到和使用数据,但是这样拿到的数据不是响应式
的,修改的时候页面上是不会发生变化的
<script setup lang="ts"> import { useTestStore } from "./store"; const store = useTestStore(); //解构state const { message, count } = store; const countAdd = () => { store.count++; }; </script> <template> <div> <div>{{ store.message }}</div> <div>{{ store.count }}</div> <hr /> <div>{{ "解构后:" + message }}</div> <div>{{ "解构后:" + count }}</div> <button @click="countAdd">count++</button> </div> </template> <style scoped> </style>
针对这种情况解决的办法就是解构的时候使用pinia的storeToRefs
方法将实例包裹住,state里的数据就变成响应式的了
import { storeToRefs } from "pinia"; //解构state,对state里的数据做了reactive处理 const { message, count } = storeToRefs(store);
状态的更新和actions的使用
在组件里修改state的状态的时候有三种方式:
- 直接修改
- $patch直接修改
- $patch通过函数修改
const countAdd = () => { // 直接修改 store.count++; store.message = 'hello pinia' // 修改多个数据 $patch批量修改 store.$patch({ count: store.count + 1, message: "hello pinia", }); // $patch 函数(推荐) store.$patch(state=>{ state.count++ state.message = "hello pinia" }) };
也可以通过actions
处理,在actions定义一个方法,通过this
访问当前实例拿到state里的数据,就像vue2的options API一样在methods里拿data里的数据
// store actions: { handleChangeState() { this.message = "hello pinia"; this.count++; }, }, //component const countAdd = () => { store.handleChangeState(); };
也可以在调用actions里的方法的时候传递参数
// store actions: { handleChangeState(num?: number) { this.count += num ?? 0; }, }, //component const countAdd = () => { store.handleChangeState(10); };
getters的使用
getters类似组件中的computed,接收一个state参数,这个state就是容器里的state状态对象,当依赖的state发生变化的时候pinia就会自动更新getters的值,而且getters具有默认的缓存机制
如果一个getter所依赖的state没有发生变化,那么就返回上一次计算的结果,而不会重新计算,显著提高了性能
// getters getters: { // typescript自动推导返回值类型 countMUL10(state) { console.log("getter被调用了"); return state.count * 10; }, // or手动指定返回值类型 countMUL10():number { console.log("getter被调用了"); return this.count * 10; }, }, //component <template> <div> <div>{{ store.count }}</div> // 调用多次 <div>{{ store.countMUL10 }}</div> <div>{{ store.countMUL10 }}</div> <div>{{ store.countMUL10 }}</div> <button @click="countAdd">count++</button> </div> </template>
store容器调用另一个store容器
如果你想在一个Store中使用另一个Store,就和在组件中使用store一样操作就可以了
import { defineStore } from "pinia"; //导入一个store容器 import { useTestStore } from "."; export const useLoginStore = defineStore("login", { state: () => { return {}; }, getters: {}, actions: { handlerOtherStore() { //得到store实例,调用实例里的方法 const testStore = useTestStore(); testStore.handleChangeState(10); }, }, });
以上就是Vue使用Pinia轻松实现状态管理的详细内容,更多关于Vue Pinia的资料请关注脚本之家其它相关文章!