一、state
1.初始化仓库store
- 安装pinia
npm install pinia
- main.ts中引入
import { createPinia } from 'pinia'
app.use(createPinia())
- src下新建store文件夹,store下新建 index.ts,以及user.ts
info.ts
export const enum Names {
TEST='TSET'
}
index.ts
存储是使用定义的defineStore()
,并且它需要一个唯一的名称,作为第一个参数传递
import {defineStore} from 'pinia'
import {Names} from './user'
//形式1
export const useTestStore = defineStore(Names.TEST,{
state:()=>{
return {
current:1,
name:'hello word'
}
},
// 也可以定义为
// state:()=>({current:1,name:'hello word'}),
getters:{
},
actions:{
change(){
this.current++
}
}
})
// 或者也可以写成如下 ---形式2
// export const useTestStore = defineStore(Names.TEST, () => {
// const current = ref(0)
// const name = ref('hahaha')
// function change() {
// current.value++
// name.value = '形式2'
// }
// return { current, name, change}
// })
2.组件中的使用store
-
直接修改
-
调用actions里面的方法
-
$patch
-
$state
$state
您可以通过将store的属性设置为新对象来替换store的整个状态
(缺点就是必须修改整个对象的所有属性)
<template>
<div class="container" ref="el">
{{ test.current }}
{{ test.name }}
<el-button @click="change">change</el-button>
</div>
</template>
<script setup lang="ts">
import {ref} from 'vue'
import {useTestStore} from '@/store/index'
const test = useTestStore()
const change = ()=>{
// 1.直接修改
test.current = 1000
test.name='xiaoluo'
// 2.调用actions里面的方法
// test.change()
// 3.$patch
// test.$patch({current:2000,name:'heiehei'})
//4.$state
// test.$state = {current:300,name:'state'}
//5.$reset $reset() 方法将状态 重置 到其初始值
test.$reset()
}
</script>
注意点:
storeToRefs()
store
是一个用reactive
包裹的对象,这意味着不需要在getter 之后写.value
,但是,就像setup
中的props
一样,我们不能对其进行解构
<template>
<div class="container" ref="el">
{{ current }}
{{ name }}
<el-button @click="change">change</el-button>
</div>
</template>
<script setup lang="ts">
import {ref} from 'vue'
import {useTestStore} from '@/store/index'
import { storeToRefs } from 'pinia'
const test = useTestStore()
// const {current,name} = test
const {current,name} = storeToRefs(test) //使用storeToRefs响应式不会丢失
const change = ()=>{
// 1.直接修改
test.current = 1000
test.name='xiaoluo'
console.log(test);//这里数据变了,但页面上数据不会变
}
</script>
3.$subscribe()和
$onAction
$subscribe()
通过 store 的 $subscribe()
方法查看状态及其变化,类似于 Vuex 的 subscribe 方法。 与常规的 watch()
相比,使用 $subscribe()
的优点是 subscriptions 只会在 patches 之后触发一次
默认情况下,state subscriptions 绑定到添加它们的组件(如果 store 位于组件的 setup()
中)。 意思是,当组件被卸载时,它们将被自动删除。 如果要在卸载组件后保留它们,请将 { detached: true }
作为第二个参数传递给 detach 当前组件的 state subscription
test.$subscribe((mutation, state) => {
console.log(mutation,state);
// 每当它发生变化时,将整个状态持久化到本地存储
localStorage.setItem('test', JSON.stringify(state))
},{ detached: true })
二、Getters
Getter 完全等同于 Store 状态的 计算值
使用场景:
import {defineStore, mapStores} from 'pinia'
import {Names} from './user'
export const useUserStore = defineStore(Names.INFO,{
state:()=>({
adress:'湖南'
}),
getters:{
userGet(state){
return state.adress+'cs'
}
}
})
// 形式1
export const useTestStore = defineStore(Names.TEST,{
// 也可以定义为
state:()=>({current:1,name:'hello word',age:25}),
getters:{
// 自动将返回类型推断为数字
doubleCurrent(state):number{
return state.current *2
},
// 返回类型必须明确设置
doubleName():string{
return this.name +' No.1'
},
// 访问其他 getter
getOthers():number{
return this.doubleCurrent*3
},
//将参数传递给 getter
getParams:(state) =>{
return (num:number) =>state.current*num
},
// 访问其他 Store 的getter
getOtherStore(state){
const user = useUserStore()
return user.userGet
}
},
})
组件中使用getter和使用state一样
三、Actions
export const useUserStore = defineStore(Names.INFO,{
state:()=>({
adress:'湖南'
}),
getters:{
userGet(state){
return state.adress+'cs'
}
}
})
const login = ():Promise<string> =>{
return new Promise(resolve=>{
setTimeout(()=>{
resolve('周杰伦')
},2000)
})
}
// 形式1
export const useTestStore = defineStore(Names.TEST,{
state:()=>({current:1,name:'hello word',age:25}),
actions:{
// 同步 以及使用其他store里的数据
change(){
const user = useUserStore()
this.name = user.adress
this.current++
},
// 异步
async registerUser() {
const res = await login()
this.name = res
},
}
})
页面中调用:
import { storeToRefs } from 'pinia'
const test = useTestStore()
function add(){
test.change()
}
订阅 Actions:
使用 store.$onAction()
订阅 action 及其结果。传递给它的回调在 action 之前执行。after
处理 Promise 并允许您在 action 完成后执行函数。 以类似的方式,onError
允许您在处理中抛出错误。
const unsubscribe = someStore.$onAction(
({
name, // action 的名字
store, // store 实例
args, // 调用这个 action 的参数
after, // 在这个 action 执行完毕之后,执行这个函数
onError, // 在这个 action 抛出异常的时候,执行这个函数
}) => {
// 记录开始的时间变量
const startTime = Date.now()
// 这将在 `store` 上的操作执行之前触发
console.log(`Start "${name}" with params [${args.join(', ')}].`)
// 如果 action 成功并且完全运行后,after 将触发。
// 它将等待任何返回的 promise
after((result) => {
console.log(
`Finished "${name}" after ${
Date.now() - startTime
}ms.\nResult: ${result}.`
)
})
// 如果 action 抛出或返回 Promise.reject ,onError 将触发
onError((error) => {
console.warn(
`Failed "${name}" after ${Date.now() - startTime}ms.\nError: ${error}.`
)
})
}
)
// 手动移除订阅
unsubscribe()
四、pinia持久化插件pinia-plugin-persist
常规的store存储数据,刷新页面数据会丢失
1.安装
npm install pinia-plugin-persist
2.引入
index.ts:
import { createPinia } from "pinia"
import piniaPluginPersist from "pinia-plugin-persist"
const store = createPinia()
store.use(piniaPluginPersist)
export default store
main.ts:
import { createApp } from 'vue'
import App from './App.vue';
import {createPinia} from 'pinia'
import store from './store'
const pinia = createPinia()
const app = createApp(App)
createApp(App)
.use(pinia)
.use(store)
.mount('#app')
import {defineStore, mapStores} from 'pinia'
import {Names} from './user'
export const useUserStore = defineStore(Names.INFO,{
state:()=>({
adress:'湖南',
name:'hello'
}),
getters:{
userGet(state){
return state.adress+'cs'
}
},
persist:{
//开启 enabled 之后,默认会对整个 Store 的 state 内容进行 sessionStorage 储存
enabled: true,
strategies:[
{
key:'cus',//自定义存储的 key,默认是 store.$id,此处是INFO
storage:localStorage,//可以指定任何 extends Storage 的实例,默认是 sessionStorage
paths:['adress','name']// state 中的字段名,按组打包储存
}
]
}
}
)