热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

带你熟练掌握在vue中使用pinia全局状态管理

与vuex的区别去除了mutation选项。省去了复杂的disptach和commit流程,直接通过模块实例调用实例的actions中的方法即可触发对应action

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

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

import a from "./a"
import b from "./b"export {a,b
}

在组件中使用该状态机

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

<script setup lang&#61;&#39;ts&#39;>
// 引入pinia模块
import {a as useA ,b as useB} from "./store"
import {storeToRefs} from "pinia" // 模块是一个函数&#xff0c;函数的返回值是模块的实例
const storeA&#61;useA()
const storeB&#61;useB()/* 通过$patch直接修改store状态&#xff0c;$patch方法接收一个函数&#xff0c;函数的参数是该模块的状态
在这个函数中我们可以直接修改store状态*/

const addx&#61;()&#61;>{storeA.$patch((s)&#61;>{s.x&#43;&#43;})}
const addy&#61;()&#61;>{storeA.$patch((s)&#61;>{s.y&#43;&#43;})}
// 如果要解构使用状态需要使用该api进行转换&#xff0c;否则不具备响应式
const {x,y}&#61;storeToRefs(useA())// 通过action间接修改store状态
const setAge&#61;()&#61;>{// 异步action返回promise。原理也很简单&#xff0c;async函数的返回值是promisestoreB.setAge(20).then(()&#61;>{console.log(&#39;age is be updated success&#39;)})
}// 通过 $subscribe监听状态的变更
storeB.$subscribe((c,s)&#61;>{ // state变化时回调。有变化信息和状态两个参数
// console.log(c)
// console.log(s)
},{detached:false, // 在组件卸载时是否继续监听deep:true, // 是否深度监听flush:&#39;post&#39;, // post:组件更新后执行&#xff1b;sync:始终同步触发&#xff1b;pre:组件更新前执行
})// 通过$onAction监听action的调用
storeB.$onAction((c)&#61;>{ // 当调用action时回调// console.log(c)// c.after(()&#61;>{console.log(&#39;after caller&#39;)}) //after的回调在该函数中最后执行// console.log(&#39;action&#39;)
},false) // 为true时&#xff0c;组件卸载时也监听该行为// 通过$reset重置对应模块的状态
const reSetAge&#61;()&#61;>{ storeB.$reset()
}
script><template><h3>模块ah3><p>({{storeA.x}},{{storeA.y}})p><button &#64;click&#61;"addx">x&#43;&#43;button><button &#64;click&#61;"addy">y&#43;&#43;button><h3>模块bh3><p>用户信息&#xff1a;{{storeB.userInfo}}p><button &#64;click&#61;"setAge">setAgebutton><button &#64;click&#61;"reSetAge">reSetAgebutton>template>

运行结果:
在这里插入图片描述


pinia模块实例中的api讲解

1.获取模块实例

// 引入模块
import {a as useA ,b as useB} from "./store" // 模块是一个函数&#xff0c;函数的返回值是模块的实例
const storeA&#61;useA()
const storeB&#61;useB()

2.提供实例修改对应模块的状态
i&#xff1a;直接修改

/* 通过$patch直接修改store状态&#xff0c;$patch方法接收一个函数&#xff0c;函数的参数是该模块的状态
在这个函数中我们可以直接修改store状态*/

const addx&#61;()&#61;>{storeA.$patch((s)&#61;>{s.x&#43;&#43;})}
const addy&#61;()&#61;>{storeA.$patch((s)&#61;>{s.y&#43;&#43;})}

ii&#xff1a;间接修改

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

3.状态的解构使用

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

4.监听状态的变更

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

5.监听action的触发

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

6.重置状态

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

7.注册插件

import {createPinia} from &#39;pinia&#39;
// plugin是一个函数
createPinia().use(Plugin)

状态持久化

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

import {PiniaPluginContext} from &#39;pinia&#39;
import {toRaw } from &#39;vue&#39; // 封装pinia持久化插件。执行时机&#xff1a;store初始化时&#xff0c;执行次数是模块的次数
export default function(type:&#39;localStorage&#39; | &#39;sessionStorage&#39;){return (ctx:PiniaPluginContext)&#61;>{// console.log(ctx)// const {app,options,pinia,store}&#61;ctx/*app:vue应用 &#xff1b;options&#xff1a;导出pinia模块的选项pinia&#xff1a;pinia app &#xff1b; store&#xff1a;pinia的store实例*/const store&#61; ctx.store // 每次执行时的store是关于那个模块的storeconst storeWay&#61;type&#61;&#61;&#61;&#39;localStorage&#39;?localStorage:sessionStorage// console.log(store)store.$subscribe(()&#61;>{ // console.log(toRaw(store.$state))storeWay.setItem(&#39;pinia_&#39;&#43;store.$id,JSON.stringify(toRaw(store.$state)))},{deep:true})// return的值为store初始状态。pinia处理过了&#xff0c;如果为retrun为null使用模块的初始值&#xff0c;return JSON.parse(storeWay.getItem(&#39;pinia_&#39;&#43;store.$id) as any)}
}

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

import { createApp} from &#39;vue&#39;
import App from &#39;./App.vue&#39;
import {createPinia} from &#39;pinia&#39;
// import {PiniaVuePlugin} from &#39;pinia&#39; // vue2
import persistence from "./plugins/pinia/persistence"const app&#61;createApp(App)// app.use(createPinia().use(persistence(&#39;sessionStorage&#39;))) //sessionStorage方式持久化
app.use(createPinia().use(persistence(&#39;localStorage&#39;))) //localStorage方式持久化app.mount(&#39;#app&#39;)

推荐阅读
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文介绍了在wepy中运用小顺序页面受权的计划,包含了用户点击作废后的从新受权计划。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • Webpack5内置处理图片资源的配置方法
    本文介绍了在Webpack5中处理图片资源的配置方法。在Webpack4中,我们需要使用file-loader和url-loader来处理图片资源,但是在Webpack5中,这两个Loader的功能已经被内置到Webpack中,我们只需要简单配置即可实现图片资源的处理。本文还介绍了一些常用的配置方法,如匹配不同类型的图片文件、设置输出路径等。通过本文的学习,读者可以快速掌握Webpack5处理图片资源的方法。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 预备知识可参考我整理的博客Windows编程之线程:https:www.cnblogs.comZhuSenlinp16662075.htmlWindows编程之线程同步:https ... [详细]
  • Java自带的观察者模式及实现方法详解
    本文介绍了Java自带的观察者模式,包括Observer和Observable对象的定义和使用方法。通过添加观察者和设置内部标志位,当被观察者中的事件发生变化时,通知观察者对象并执行相应的操作。实现观察者模式非常简单,只需继承Observable类和实现Observer接口即可。详情请参考Java官方api文档。 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文介绍了最长上升子序列问题的一个变种解法,通过记录拐点的位置,将问题拆分为左右两个LIS问题。详细讲解了算法的实现过程,并给出了相应的代码。 ... [详细]
  • 本文讨论了一个数列求和问题,该数列按照一定规律生成。通过观察数列的规律,我们可以得出求解该问题的算法。具体算法为计算前n项i*f[i]的和,其中f[i]表示数列中有i个数字。根据参考的思路,我们可以将算法的时间复杂度控制在O(n),即计算到5e5即可满足1e9的要求。 ... [详细]
author-avatar
999欢_879
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有