文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

vue中使用pinia全局状态管理的实现

2024-04-02 19:55

关注

与vuex的区别

去除了 mutation 选项。省去了复杂的disptachcommit流程,直接通过模块实例调用实例的actions中的方法即可触发对应action;在组件中直接可以通过模块实例的$patch修改store状态或者通过action来间接修改store状态。响应式数据原理是proxy,使得数据的增加或者删除字段都具备响应式。

安装

yarn add pinia

引入pinia

main.ts中注册pinia插件

import {createPinia} from 'pinia'    // vue3
// import {PiniaVuePlugin} from 'pinia' // vue2

const app=createApp(App)
app.use(createPinia())
app.mount('#app')

创建状态目录

在src下创建文件夹store,在store下创建文件index.ts,a.ts,b.ts。a.ts和b.ts分别是管理某个状态的模块,index.ts用来整合这些模块。

pinia模块组成

state、actions、getters。

创建pinia模块

对应选项的含义看代码注释。
1.在a.js编写如下代码

import {defineStore} from "pinia"

export default defineStore('a',{    // a是模块的命名空间,不能和其他模块的一样
    state:()=>({         // state是一个函数,函数返回值为管理的状态
        x:0,
        y:0,
    }),
 })

2.在b.ts编写如下代码

import {defineStore} from "pinia"

export default defineStore('b',{
    state:()=>({
        name:'b',
        age:18,
    }),
    actions:{
        print(msg:string){     // 同步action
            console.log(msg)
         },
        async setAge(newAge:number){       // 异步action
            // 模拟接口
            const setAgeReq=<T>(age:T)=>new Promise<T>((rel)=>{
                setTimeout(()=>{rel(age)},1000)
            })
            
            const age=await setAgeReq(newAge)
            // 在action中通过实例来直接修改状态
            this.age=age   
            // 在action中也可以通过实例直接调用其他action 
            // this.print('age is be updated success')   
        }
    },
    getters:{ 
        // 和vuex的getters一样,返回一个值就行了。和computed一样具有缓存机制               
        userInfo():string{    
            return `name:${this.name} age:${this.age}`
        }
    },


})

3.在index.ts中整合所有模块

import a from "./a"
import b from "./b"

export {
   a,b
}

在组件中使用该状态机

pinia的api基本都在该案例中,注释和代码都很容易理解,相信小伙伴们都看的懂。如果不是很明白,可以看下一章节的api讲解,看懂的可以跳过api讲解章节。

<script setup lang='ts'>
// 引入pinia模块
import {a as useA ,b as useB} from "./store"  
import {storeToRefs} from "pinia" 

// 模块是一个函数,函数的返回值是模块的实例
const storeA=useA()
const storeB=useB()


const addx=()=>{storeA.$patch((s)=>{s.x++})}
const addy=()=>{storeA.$patch((s)=>{s.y++})}
// 如果要解构使用状态需要使用该api进行转换,否则不具备响应式
const {x,y}=storeToRefs(useA())

// 通过action间接修改store状态
const setAge=()=>{
 // 异步action返回promise。原理也很简单,async函数的返回值是promise
 storeB.setAge(20).then(()=>{console.log('age is be updated success')})
}

// 通过 $subscribe监听状态的变更
storeB.$subscribe((c,s)=>{  // state变化时回调。有变化信息和状态两个参数
//    console.log(c)
//    console.log(s)
},{
	detached:false,  // 在组件卸载时是否继续监听
	deep:true,  // 是否深度监听
	flush:'post',  // post:组件更新后执行;sync:始终同步触发;pre:组件更新前执行
})

// 通过$onAction监听action的调用
storeB.$onAction((c)=>{   // 当调用action时回调
    // console.log(c)
    // c.after(()=>{console.log('after caller')})  //after的回调在该函数中最后执行
    // console.log('action')
},false)   // 为true时,组件卸载时也监听该行为

// 通过$reset重置对应模块的状态
const reSetAge=()=>{  
   storeB.$reset()
}

</script>

<template>
	<h3>模块a</h3>
	<p>({{storeA.x}},{{storeA.y}})</p>
	<button @click="addx">x++</button>
	<button @click="addy">y++</button>
	<h3>模块b</h3>
	<p>用户信息:{{storeB.userInfo}}</p>
	<button @click="setAge">setAge</button>
	<button @click="reSetAge">reSetAge</button>

</template>

运行结果:

pinia模块实例中的api讲解

1.获取模块实例

// 引入模块
import {a as useA ,b as useB} from "./store"  

// 模块是一个函数,函数的返回值是模块的实例
const storeA=useA()
const storeB=useB()

2.提供实例修改对应模块的状态
i:直接修改


const addx=()=>{storeA.$patch((s)=>{s.x++})}
const addy=()=>{storeA.$patch((s)=>{s.y++})}

ii:间接修改

import {storeToRefs} from "pinia" 
// 如果要解构使用状态需要使用该api进行转换,否则不具备响应式
const {x,y}=storeToRefs(useA())

3.状态的解构使用

import {storeToRefs} from "pinia" 
// 如果要解构使用状态需要使用该api进行转换,否则不具备响应式
const {x,y}=storeToRefs(useA())

4.监听状态的变更

// 通过 $subscribe监听状态的变更
storeB.$subscribe((c,s)=>{  // state变化时回调。有变化信息和状态两个参数
//    console.log(c)
//    console.log(s)
},{
detached:false,  // 在组件卸载时是否继续监听
deep:true,  // 是否深度监听
flush:'post',  // post:组件更新后执行   ,sync:始终同步触发     ,pre:组件更新前执行
})

5.监听action的触发

// 通过$onAction监听action的调用
storeB.$onAction((c)=>{   // 当调用action时回调
    // console.log(c)
    // c.after(()=>{console.log('after caller')})  //after的回调在该函数中最后执行
    // console.log('action')
},false)   // 为true时,组件卸载时也监听该行为

6.重置状态

// 通过$reset重置对应模块的状态
const reSetAge=()=>{  
   storeB.$reset()
}

7.注册插件

import {createPinia} from 'pinia'
// plugin是一个函数 
createPinia().use(Plugin)   

状态持久化

这里需要使用到注册插件的功能。首先在src/plugins/pinia/persistence.ts中编写如下代码

import {PiniaPluginContext} from 'pinia'
import {toRaw } from 'vue' 

// 封装pinia持久化插件。执行时机:store初始化时,执行次数是模块的次数
export default function(type:'localStorage' | 'sessionStorage'){
   
    return (ctx:PiniaPluginContext)=>{
       //    console.log(ctx)
   // const {app,options,pinia,store}=ctx
   
   const store= ctx.store    // 每次执行时的store是关于那个模块的store
   const storeWay=type==='localStorage'?localStorage:sessionStorage
   // console.log(store)
   store.$subscribe(()=>{  
      // console.log(toRaw(store.$state))
      
      storeWay.setItem('pinia_'+store.$id,JSON.stringify(toRaw(store.$state)))
   },{deep:true})
   
    // return的值为store初始状态。pinia处理过了,如果为retrun为null使用模块的初始值,
    return JSON.parse(storeWay.getItem('pinia_'+store.$id) as any)
    }
}

然后在mian.js编写如下代码即可。此时刷新浏览器刷新时,状态是可以保持的,不会被重置。

import { createApp} from 'vue'
import App from './App.vue'
import {createPinia} from 'pinia' 
// import {PiniaVuePlugin} from 'pinia' // vue2
import persistence from "./plugins/pinia/persistence"

const app=createApp(App)

// app.use(createPinia().use(persistence('sessionStorage')))   //sessionStorage方式持久化
app.use(createPinia().use(persistence('localStorage')))  //localStorage方式持久化

app.mount('#app')

到此这篇关于vue中使用 pinia 全局状态管理的实现的文章就介绍到这了,更多相关vue pinia 全局状态管理内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-前端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯