【vue】vue3中状态管理Pinia(Vuex5)使用快速上手

Pinia和Vuex一样都是是vue的全局状态管理器。其实Pinia就是Vuex5,只不过为了尊重原作者的贡献就沿用了名字Pinia。

关于vuex的介绍可以查看我之前的文章前端状态管理之Vuex全解析

一、安装

npm i pinia -S

二、挂载

2.1 main.js引入

import { createApp } from "vue";
import App from "./App.vue";
import {createPinia} from 'pinia';
const pinia = createPinia();
createApp(App).use(pinia).mount("#app");

2.2 创建Store

src下新建piniaStore/storeA.js

import { defineStore } from "pinia";

export const storeA = defineStore("storeA", {
  state: () => {
    return {
      piniaMsg: "hello pinia",
    };
  },
  getters: {},
  actions: {},
});

2.3 App.vue使用

<template>
  <div>div>
template>
<script setup>
import { storeA } from '@/piniaStore/storeA'
let piniaStoreA = storeA()
console.log(piniaStoreA.piniaMsg); //hello pinia
script>

从这里我们可以看出pinia中没有了mutationsmodulespinia不必以嵌套(通过modules引入)的方式引入模块,因为它的每个store便是一个模块,如storeAstoreB… 。
在我们使用Vuex的时候每次修改state的值都需要调用mutations里的修改函数,因为Vuex需要追踪数据的变化,这使我们写起来比较繁琐。
pinia则不再需要mutations,同步异步都可在actions进行操作,至于它没有了mutations具体是如何最终到state变化的。

三、修改状态

3.1 直接修改

相比于VuexPinia是可以直接修改状态的,并且调试工具能够记录到每一次state的变化,如App.vue

<template>
  <div>{{ piniaStoreA.piniaMsg }}div>
template>
<script setup>
import { storeA } from '@/piniaStore/storeA'

let piniaStoreA = storeA()
console.log(piniaStoreA.piniaMsg); //hello pinia

piniaStoreA.piniaMsg = 'hello juejin'
console.log(piniaStoreA.piniaMsg); //hello juejin
script>

3.2 $patch修改

使用$patch方法可以修改多个state中的值,比如我们在piniaStore/storeA.js中的state增加一个name

import { defineStore } from "pinia";

export const storeA = defineStore("storeA", {
  state: () => {
    return {
      piniaMsg: "hello pinia",
      name: "xiaoyue",
    };
  },
  getters: {},
  actions: {},
});

然后我们在App.vue中进行修改这两个state

import { storeA } from '@/piniaStore/storeA';

let piniaStoreA = storeA()
console.log(piniaStoreA.name); //xiaoyue
piniaStoreA.$patch({
  piniaMsg: 'hello juejin',
  name: 'daming'
})
console.log(piniaStoreA.name);//daming

当然也是支持修改单个状态的如

piniaStoreA.$patch({
  name: 'daming'
})

$patch还可以使用函数的方式进行修改状态

import { storeA } from '@/piniaStore/storeA';

let piniaStoreA = storeA()
cartStore.$patch((state) => {
  state.name = 'daming'
  state.piniaMsg = 'hello juejin'
})

3.3 在actions中进行修改

不同于Vuex的是,Pinia去掉了mutations,所以在actions中修改state就行Vuexmutations修改state一样。其实这也是我比较推荐的一种修改状态的方式,就像上面说的,这样可以实现整个数据流程都在状态管理器内部,便于管理。
piniaStore/storeA.jsactions添加一个修改name的函数

import { defineStore } from "pinia";

export const storeA = defineStore("storeA", {
  state: () => {
    return {
      piniaMsg: "hello pinia",
      name: "xiao yue",
    };
  },
  actions: {
    setName(data) {
      this.name = data;
    },
  },
});

组件App.vue中调用不需要再使用dispatch函数,直接调用store的方法即可

import { storeA } from '@/piniaStore/storeA';

let piniaStoreA = storeA()
piniaStoreA.setName('daming')

3.4 重置state

Pinia可以使用$reset将状态重置为初始值

import { storeA } from '@/piniaStore/storeA';

let piniaStoreA = storeA()
piniaStoreA.$reset()

四、Pinia解构(storeToRefs)

当我们组件中需要用到state中多个参数时,使用解构的方式取值往往是很方便的,但是传统的ES6解构会使state失去响应式,比如组件App.vue,我们先解构取得name值,然后再去改变name值,然后看页面是否变化

<template>
  <div>{{ name }}div>
template>
<script setup>
import { storeA } from '@/piniaStore/storeA';

let piniaStoreA = storeA()
let { piniaMsg, name } = piniaStoreA
piniaStoreA.$patch({
  name: 'daming'
})
script>
  • 我们可以发现浏览器并没有更新为daming
    为了解决这个问题,Pinia提供了一个结构方法storeToRefs,我们将组件App.vue使用storeToRefs解构
<template>
  <div>{{ name }}div>
template>
<script setup>
import { storeA } from '@/piniaStore/storeA';
import { storeToRefs } from 'pinia';

let piniaStoreA = storeA()
let { piniaMsg, name } = storeToRefs(piniaStoreA)
piniaStoreA.$patch({
  name: 'daming'
})

script>

此时我们发现页面已经被更新成daming了

五、getters

其实Vuex中的getters和Pinia中的getters用法是一致的,用于自动监听对应state的变化,从而动态计算返回值(和vue中的计算属性差不多),并且getters的值也具有缓存特性。
我们先将piniaStore/storeA.js改为:

import { defineStore } from "pinia";

export const storeA = defineStore("storeA", {
  state: () => {
    return {
      count1: 1,
      count2: 2,
    };
  },
  getters: {
    sum() {
      console.log('我被调用了!')
      return this.count1 + this.count2;
    },
  },
});

然后在组件App.vue中获取sum

<template>
  <div>{{ piniaStoreA.sum }}</div>
</template>
<script setup>
import { storeA } from '@/piniaStore/storeA'
let piniaStoreA = storeA()
console.log(piniaStoreA.sum) //3

</script>

让我们来看下什么是缓存特性。首先我们在组件多次访问sum再看下控制台打印

import { storeA } from '@/piniaStore/storeA';

let piniaStoreA = storeA()
console.log(piniaStoreA.sum)
console.log(piniaStoreA.sum)
console.log(piniaStoreA.sum)
piniaStoreA.count1 = 2
console.log(piniaStoreA.sum)

【vue】vue3中状态管理Pinia(Vuex5)使用快速上手_第1张图片
从打印结果我们可以看出只有在首次使用用或者当我们改变sum所依赖的值的时候,getters中的sum才会被调用

六、modules

如果项目比较大,使用单一状态库,项目的状态库就会集中到一个大对象上,显得十分臃肿难以维护。所以Vuex就允许我们将其分割成模块modules,每个模块都拥有自己state,mutations,actions...
Pinia每个状态库本身就是一个模块。

Pinia没有modules,如果想使用多个store,直接定义多个store传入不同的id即可,如:

import { defineStore } from "pinia";

export const storeA = defineStore("storeA", {...});
export const storeB = defineStore("storeB", {...});
export const storeC = defineStore("storeB", {...});

通过以上案例我们会发现Pinia比Vuex简洁许多,所以如果我们的项目是新项目的话建议使用Pinia。

https://juejin.cn/post/7121209657678364685

你可能感兴趣的:(vue,vue.js,javascript,前端,状态管理,pinia)