Pinia使用说明Vue3状态管理组件

本文参考:https://blog.csdn.net/qq1195566313/article/details/123338137

https://pinia.web3doc.top/
状态管理组件,代替vuex
image.png

_Pinia.js 有如下特点:_

  • 完整的 ts 的支持;
  • 足够轻量,压缩后的体积只有1kb左右;
  • 去除 mutations,只有 state,getters,actions;
  • actions 支持同步和异步;
  • 代码扁平化没有模块嵌套,只有 store 的概念,store 之间可以自由使用,每一个store都是独立的
  • 无需手动添加 store,store 一旦创建便会自动添加;
  • 支持Vue3 和 Vue2

安装

安装命令:
yarn add pinia
注册:
vue3在main.js中

import {createApp} from 'vue'
import App from './App.vue'
import {createPinia} from "pinia";

//引入pinia
const store = createPinia()

let app = createApp(App)

app.use(store).mount('#app')

vue2使用


import { createPinia, PiniaVuePlugin } from 'pinia'
 
Vue.use(PiniaVuePlugin)
const pinia = createPinia()
 
new Vue({
  el: '#app',
  // other options...
  // ...
  // note the same `pinia` instance can be used across multiple Vue apps on
  // the same page
  pinia,
})

创建仓库

image.png
定义仓库defineStore,第一个值为仓库id

import {defineStore} from "pinia";
import {Names} from "./store-name";

export const useTestStore = defineStore(Names.TEST,{
  
    state:()=>{
        return{
            name:'zhouzhou',
            age:22
        }
    },
    //computed 有缓存,修饰一些值
    getters:{

    },
    //methods 可以同步也可以异步 提交state
    actions:{

    }


})
export const enum Names {
    TEST = 'TEST'
}

state

pinia修改状态一共有五种方式:
导入方式 :import {useTestStore} from ‘…/store’
const Test = useTestStore()
Test.name就可以取到值

<template>
  <b-comp></b-comp>
  <div>
    pinia:{{Test.name}}++{{Test.age}}
  </div>
  <button @click="changeValue">changeValue</button>
</template>

<script setup lang="ts">
  import BComp from "./BComp/index.vue"
  import {useTestStore} from '../store'

  /**
   * pinia修改值的五种方式
   * 1.直接修改  Test.name = 'qiqi'在Vuex中必须通过mutation提交,而pinia没有这种限制
   * 2.通过$patch修改,传入一个对象,可以批量修改
   * Test.$patch({
   *       name:'qiqi',
   *       age:23
   *     })
   * 3.$patch传入函数,推荐使用这种方式,可以在其中写一些逻辑
   *    Test.$patch((state)=>{
   *       state.name = 'qiqi'
   *       state.age = 22
   *     })
   * 4.$state直接替换整个state,缺点是必须要修改所有的值,一般不用
   *   Test.$state = {
   *       name:'qiqi',
   *       age:22
   *     }
   * 5.借助actions修改
   *   调用:通过Test.setName即可
   */

  const Test = useTestStore()
  const changeValue = () => {
    Test.$state = {
      name:'qiqi',
      age:22
    }
  }
  
</script>

<style scoped>

</style>

最后一种定义actions
在action中不能写箭头函数,需要通过this来获取state中的值
image.png
image.png

解构

和reactive一样,解构会丢失响应式
image.png
解决方案:pinia提供了API:storeToRefs,解构完成之后,为Ref,修改值需要通过current.value++这样的形式
image.png

actions

传参
image.png
相互调用
image.png

类似于method,可以在里面写同步以及异步代码

import {defineStore} from "pinia";
import {Names} from "./store-name";

type User = {
  name:string
  age:number
}

const login = ():Promise<User> => {
  return new Promise<User>((resolve, reject) => {
    setTimeout(() => {
      resolve({
        name:'qqqqq',
        age:32
      })
    },2000)
  })
}

export const useTestStore = defineStore(Names.TEST, {
  state: () => {
    return {
      user:{
        name: 'zhouzhou',
        age: 22
      }
    }
  },
  //computed 修饰一些值
  getters: {},
  //methods 可以同步也可以异步
  actions: {
    setName() {
      this.user.name = 'qiqi'
    },
    async setUser(){
      const result = await login()
      this.user = result
      console.log('fasdf');
    }
  }
  
  
})

getter

image.png

image.png
相互调用
image.png

API

https://blog.csdn.net/qq1195566313/article/details/123402377

$reset

重新恢复初始状态
在actions中
image.png

$subscribe

当state中的值发生改变会调用
image.png
image.png
更多参数:类似与watchEffect
image.png

$onAction

image.png
image.png
after 和 watchEffect中的before很像,接收一个工厂函数,在$onAction的代码执行完之后调用
image.png
第二个参数,布尔值,当为true的时候,组件实例销毁后onAction依然存活
image.png

pinia持久化

pinia和vuex都有一个共同的问题:当刷新页面之后,数据就消失了(恢复原始数据,之前的操作不会保留)

手写持久化

使用pinia插件(main.js)
image.png

返回值:
image.png
总之我们要实现这个插件我们需要每次修改值就给它存起来

pinia-plugin.ts

import {createPinia, PiniaPluginContext} from "pinia";

//引入pinia
export const store = createPinia()

type Options = {
    key?: string
}
//如果use.store(piniaPlugin)这样,没有传参数,就使用这个值作为key
const __piniaKey__: string = 'zhoubao'

//设置缓存的方法
const setStorage = (key: string, value: any) => {
    localStorage.setItem(key, JSON.stringify(value))
}
//获取缓存的方法
const getStorage = (key: string) => {
    return localStorage.getItem(key) ? JSON.parse(localStorage.getItem(key) as string) : {}
}

//pinia插件
//函数柯里化,概念看不太懂
//我们如果不使用这个技术,那么我们每次使用这个函数,就必须传入两个参数,但是我们发现,第二个参数都是一样的context: PiniaPluginContext
//所以我们希望这个函数只需要有一个参数,就是key,如果我们返回一个函数,而这个函数的形参为context: PiniaPluginContext
//那么我们发现,我们这个函数只需要传入一个参数就可以了


export const piniaPlugin = (options: Options) => {

    return (context: PiniaPluginContext) => {
        //context中是当前pinia的实例,我们通过解构的方式来获取其中我们需要存储的部分,也就是store
        const {store} = context
        
        //获取缓存中存储的store数据
        const data = getStorage(`${options?.key ?? __piniaKey__}-${store.$id}`)
        
        //pinia的api,当state中数据改变的时候,就设置缓存,设置缓存的时候需要toRaw方法(将refImpl对象转化为普通对象)才能正确放进去
        store.$subscribe(() => {
            setStorage(`${options?.key ?? __piniaKey__}-${store.$id}`, toRaw(store.$state))
        })
        
        //返回缓存中的数据,将store中的数据设置为缓存的数据
        return {
            ...data
        }
    }
}

如果将pinia-plugin.ts中的代码全部放在main.ts中,代码太多了,不太行,我们将它分解出来,放在pinia-plugin.ts里面,暴露store对象以及piniaPlugin方法,最后再main.ts中使用store身上的use方法将piniaPlugin方法加载上去即可

main.ts
image.png

pinia持久化插件

npm安装 npm i pinia-plugin-persistedstate
vue3中使用:

import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
import {createPinia} from "pinia";

//使用pinia数据持久化
const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)

createApp(App).use(ElementPlus).use(router).use(pinia).mount('#app')

使用方法

    getters:{},
    //    持久化
    persist:{
        key:'terminal-config-store',
        storage:window.localStorage,
        beforeRestore:()=>{
            console.log("load terminalConfigStore data start");
        },
        afterRestore:()=>{
            console.log("load terminalConfigStore data end")
        }
    },
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值