Vue使用Pinia轻松实现状态管理

 更新时间:2023年06月08日 10:45:36   作者:格斗家不爱在外太空沉思  
pinia,一个基于Vue3的状态管理库,它可以帮助开发人员管理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的资料请关注脚本之家其它相关文章!

相关文章

  • Vue3 computed初始化获取设置值实现示例

    Vue3 computed初始化获取设置值实现示例

    这篇文章主要为大家介绍了Vue3 computed初始化以及获取值设置值实现示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-10-10
  • vue中实现上传文件给后台实例详解

    vue中实现上传文件给后台实例详解

    在本文里小编给大家分享了一篇关于vue中实现上传文件给后台的实例内容,有需要此功能的可以学习参考下。
    2019-08-08
  • 解决vue项目axios每次请求session不一致的问题

    解决vue项目axios每次请求session不一致的问题

    这篇文章主要介绍了解决vue项目axios每次请求session不一致的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-10-10
  • 详解如何在Vue组件方法中加载和使用匿名函数

    详解如何在Vue组件方法中加载和使用匿名函数

    在Vue.js的开发过程中,组件方法的定义和调用是非常常见的,有时候,为了响应事件或其他操作,我们需要在组件的方法中使用匿名函数,本文将深入探讨如何在Vue组件的方法中加载和使用匿名函数,并提供详细的代码示例和解释,帮助开发者更好地理解和应用这些技术
    2024-09-09
  • vue使用iview的modal弹窗嵌套modal出现格式错误的解决

    vue使用iview的modal弹窗嵌套modal出现格式错误的解决

    这篇文章主要介绍了vue使用iview的modal弹窗嵌套modal出现格式错误的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-09-09
  • vue中手动封装iconfont组件解析(三种引用方式的封装和使用)

    vue中手动封装iconfont组件解析(三种引用方式的封装和使用)

    这篇文章主要介绍了vue中手动封装iconfont组件(三种引用方式的封装和使用),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-09-09
  • vue3 ref获取组件实例详细图文教程

    vue3 ref获取组件实例详细图文教程

    在Vue3中可以使用ref函数来创建一个响应式的变量,通过将ref函数应用于一个组件实例,我们可以获取到该组件的实例对象,这篇文章主要给大家介绍了关于vue3 ref获取组件实例的详细图文教程,需要的朋友可以参考下
    2023-10-10
  • 脚手架vue-cli工程webpack的作用和特点

    脚手架vue-cli工程webpack的作用和特点

    webpack是一个模块打包的工具,它的作用是把互相依赖的模块处理成静态资源。这篇文章主要介绍了vue-cli工程webpack的作用和特点,需要的朋友可以参考下
    2018-09-09
  • vue+swiper实现时间轴效果

    vue+swiper实现时间轴效果

    这篇文章主要为大家详细介绍了vue+swiper实现时间轴效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • vue中如何去掉input前后的空格

    vue中如何去掉input前后的空格

    这篇文章主要介绍了vue中如何去掉input前后的空格问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03

最新评论