Vue3-Pinia-状态管理器

272 阅读4分钟

Vue3-Pinia-状态管理器

目录

  • pinia是什么?
  • pinia的核心概念
  • pinia 持久化插件

内容一 pinia是什么

概念:

Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状态。在我们开发一个web端系统或者app时,有一些数据需要我们在好多个页面使用,例如 用户的登录信息,用户的权限信息等,这时我们就可以用pinia 将这些信息存在state中,从而实现每个页面都可以使用。

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

内容二 pinia核心概念

定义仓库Store :

Store 是用 defineStore() 来定义,

defineStore() 第一个参数:要求为独一无二的名字,也用作 id ,必须传入;

defineStore()第二个参数:可接受两类值:Setup 函数或 Option 对象。Vue 组合式 API 的 setup 函数 相似。本人习惯使用Option (更直观简单),下列展示Option 示例:

import { defineStore } from 'pinia'

export const meStore = defineStore('me', {  

  state: () => ( { Count: 0 } ),
 
  getters: {
    double: (state) => state.Count * 2 ,
  },
  
  actions: {
    increment() {
      this.Count++
    }
  }
  
})

可以认为 state 是 store 的数据 (data),getters 是 store 的计算属性 (computed),而 actions 则是方法 (methods)。

使用Store:

<script setup>

import { meStore } from '@/stores/me'   

const store = meStore()       // 可以在组件中的任意位置访问 `store` 变量 ✨

</script>

一旦 store 被实例化,你可以直接访问在 store 的 stategettersactions 中定义的任何属性。

State

定义State:

state 是 store仓库 的核心,用来定义初始化的值。当state 中值发生改变时,调用其的子组件都会得到相应的更新。

import { defineStore } from 'pinia'

const meStore = defineStore('me', {
  state: () => {
    return {
         name:'月月',
         age:18
    }
  }
})
访问State

在其他组件中访问:

const store = meStore()

console.log('姓名:', store.name)

在Store内部访问(getters / actions):

this.age++

console.log('年龄:', this.age)

修改State

除了用 store.age++ 直接改变 store,你还可以调用 $patch 方法批量修改 。

  • $patch 对象模式:
import { meStore } from '@/stores/me' 

const store = meStore()  

store.$patch({
name: '哈哈',
age: 19
})

弊端:无法处理逻辑

  • $patch 函数模式:
store.$patch((state) => {

  state.items.push({ quantity: 1 })
  
  state.name = '哈哈'

})

可以处理逻辑

  • 还可以在actions写方法修改 再进行调用

actions: {

updateName() {
this.name = '哈哈'
}

}
替换State

$state您可以通过将store的属性设置为新对象来替换store的整个状态。 (覆盖 也可以修改state 不建议)

import { meStore } from '@/stores/me'

const store = meStore() 

const Add = () => {
    store.$state = {
       name:'丫丫',
       age:30
    }    

弊端:必须修改整个对象的所有属性

重置State

$reset() 会把state所有值 重置回 原始状态

const store = meStore()

store.$reset()
侦听 state

$subscribe() 方法侦听 state及值的变化。一变化就会调用这个函数,可在里面做事件。

store.$subscribe((args, state) => {

 console.log(args,state);

})

如果你的组件卸载之后还想继续调用请设置第二个参数

store.$subscribe((args, state) => {

 console.log(args,state);

},{
  detached:true     //  卸载之后可继续调用
})
解构 state

根据实例进行解构,不具有响应式,可使用API storeToRefs 将结构出来的值变成响应式。

import { storeToRefs } from 'pinia'
 
const store = meStore()
 
const { age, name } = storeToRefs(store)

Getter

Getter 相当于storestate 的计算属性。

箭头函数
  • 使用箭头函数,它将接收 state 作为第一个参数,不能使用this
export const meStore = defineStore('me', {
    state: () => {
        return{
              count: 0,
              name:'月月'
     }
   },

    getters: {
         doubleCount: (state) => state.count * 2,
    }

})
常规函数
  • 在使用常规函数定义 getter 时,我们也可以通过 this 访问到整个 store 实例
export const meStore = defineStore('me', {
  state: () => {
   return {
      count: 0
   }
  },
  
  getters: {
    doubleCount():number {
    return this.count + 1
    }
  }
  
})
互相调用
  • getters 内函数可以互相调用
    getters:{
       newCurrent ():number | string {
           return ++this.count + this.newName
       },
       newName ():string {
           return `$-${this.name}`
       }
    },

Actions

Actions 相当于组件中的 method,支持同步异步函数。action 也可通过 this 访问整个 store 实例

同步
import { defineStore } from 'pinia'
export const meStore = defineStore(me, {
    state: () => {
     return {
        count: 0
     }
    },
    actions: {
        increment() {
            this.count++
        },
        randomizeCounter() {
            this.count = Math.round(100 * Math.random())
        },
    },
})

​ 组件使用

<script setup lang='ts'>
import {meStore} from './me'

const store = meStore()
const Add = () => {
     store.randomizeCounter()
}
 
</script>
异步
  • 可以结合async await 修饰
 async getLoginInfo() {
            const result = await Login()
            this.user = result;
        }
相互调用
  • Actions 内的方法可相互调用
import { defineStore } from 'pinia'
export const meStore = defineStore(me, {
    state: () => {
       return {
        count: 0
       }
    },
    actions: {
        increment() {
            this.count++
        },
        randomizeCounter() {
            this.count = Math.round(100 * Math.random())
            if(....可写逻辑){
            this.increment()    // 调用其他方法
            }
        }
    }
})
侦听Actions
  • 只要有actions被调用就会走这个函数
store.$onAction((args)=>{
   console.log(args);
   
})

内容三 pinia持久化插件

piniavuex 都有一个通病,页面刷新状态会丢失。所以在使用时可搭配pinia持久化插件一起使用。可在插件库搜索符合项目的插件。