作者:999欢_879 | 来源:互联网 | 2023-08-11 00:19
与vuex的区别去除了mutation选项。省去了复杂的disptach和commit流程,直接通过模块实例调用实例的actions中的方法即可触发对应action
与vuex的区别
去除了 mutation
选项。省去了复杂的disptach
和commit
流程,直接通过模块实例调用实例的actions
中的方法即可触发对应action
;在组件中直接可以通过模块实例的$patch
修改store
状态或者通过action
来间接修改store
状态。响应式数据原理是proxy
,使得数据的增加或者删除字段都具备响应式。
安装
yarn add pinia
引入pinia
在main.ts
中注册pinia插件
import {createPinia} from 'pinia'
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',{ 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){ console.log(msg)},async setAge(newAge:number){ const setAgeReq&#61;<T>(age:T)&#61;>new Promise<T>((rel)&#61;>{setTimeout(()&#61;>{rel(age)},1000)})const age&#61;await setAgeReq(newAge)this.age&#61;age }},getters:{ 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;>
import {a as useA ,b as useB} from "./store"
import {storeToRefs} from "pinia"
const storeA&#61;useA()
const storeB&#61;useB()
const addx&#61;()&#61;>{storeA.$patch((s)&#61;>{s.x&#43;&#43;})}
const addy&#61;()&#61;>{storeA.$patch((s)&#61;>{s.y&#43;&#43;})}
const {x,y}&#61;storeToRefs(useA())
const setAge&#61;()&#61;>{storeB.setAge(20).then(()&#61;>{console.log(&#39;age is be updated success&#39;)})
}
storeB.$subscribe((c,s)&#61;>{
},{detached:false, deep:true, flush:&#39;post&#39;,
})
storeB.$onAction((c)&#61;>{
},false)
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"
const storeA&#61;useA()
const storeB&#61;useB()
2.提供实例修改对应模块的状态
i&#xff1a;直接修改
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;间接修改
const setAge&#61;()&#61;>{
storeB.setAge(20).then(()&#61;>{console.log(&#39;age is be updated success&#39;)})
}
3.状态的解构使用
import {storeToRefs} from "pinia"
const {x,y}&#61;storeToRefs(useA())
4.监听状态的变更
storeB.$subscribe((c,s)&#61;>{
},{
detached:false,
deep:true,
flush:&#39;post&#39;,
})
5.监听action的触发
storeB.$onAction((c)&#61;>{
},false)
6.重置状态
const reSetAge&#61;()&#61;>{ storeB.$reset()
}
7.注册插件
import {createPinia} from &#39;pinia&#39;
createPinia().use(Plugin)
状态持久化
这里需要使用到注册插件的功能。首先在src/plugins/pinia/persistence.ts
中编写如下代码
import {PiniaPluginContext} from &#39;pinia&#39;
import {toRaw } from &#39;vue&#39;
export default function(type:&#39;localStorage&#39; | &#39;sessionStorage&#39;){return (ctx:PiniaPluginContext)&#61;>{const store&#61; ctx.store const storeWay&#61;type&#61;&#61;&#61;&#39;localStorage&#39;?localStorage:sessionStoragestore.$subscribe(()&#61;>{ storeWay.setItem(&#39;pinia_&#39;&#43;store.$id,JSON.stringify(toRaw(store.$state)))},{deep:true})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 persistence from "./plugins/pinia/persistence"const app&#61;createApp(App)
app.use(createPinia().use(persistence(&#39;localStorage&#39;))) app.mount(&#39;#app&#39;)