本文参考:https://blog.csdn.net/qq1195566313/article/details/123338137
https://pinia.web3doc.top/
状态管理组件,代替vuex
_Pinia.js 有如下特点:_
安装命令:yarn add pinia
注册:
vue3在main.js中
import {createApp} from 'vue'
import App from './App.vue'
import {createPinia} from "pinia";
//引入pinia
const store = createPinia()
let app = createApp(App)
app.use(store).mount('#app')
vue2使用
import { createPinia, PiniaVuePlugin } from 'pinia'
Vue.use(PiniaVuePlugin)
const pinia = createPinia()
new Vue({
el: '#app',
// other options...
// ...
// note the same `pinia` instance can be used across multiple Vue apps on
// the same page
pinia,
})
import {defineStore} from "pinia";
import {Names} from "./store-name";
export const useTestStore = defineStore(Names.TEST,{
state:()=>{
return{
name:'zhouzhou',
age:22
}
},
//computed 有缓存,修饰一些值
getters:{
},
//methods 可以同步也可以异步 提交state
actions:{
}
})
export const enum Names {
TEST = 'TEST'
}
pinia修改状态一共有五种方式:
导入方式 :import {useTestStore} from ‘…/store’
const Test = useTestStore()
Test.name就可以取到值
pinia:{{Test.name}}++{{Test.age}}
最后一种定义actions
在action中不能写箭头函数,需要通过this来获取state中的值
和reactive一样,解构会丢失响应式
解决方案:pinia提供了API:storeToRefs,解构完成之后,为Ref,修改值需要通过current.value++这样的形式
类似于method,可以在里面写同步以及异步代码
import {defineStore} from "pinia";
import {Names} from "./store-name";
type User = {
name:string
age:number
}
const login = ():Promise<User> => {
return new Promise<User>((resolve, reject) => {
setTimeout(() => {
resolve({
name:'qqqqq',
age:32
})
},2000)
})
}
export const useTestStore = defineStore(Names.TEST, {
state: () => {
return {
user:{
name: 'zhouzhou',
age: 22
}
}
},
//computed 修饰一些值
getters: {},
//methods 可以同步也可以异步
actions: {
setName() {
this.user.name = 'qiqi'
},
async setUser(){
const result = await login()
this.user = result
console.log('fasdf');
}
}
})
https://blog.csdn.net/qq1195566313/article/details/123402377
当state中的值发生改变会调用
更多参数:类似与watchEffect
after 和 watchEffect中的before很像,接收一个工厂函数,在$onAction的代码执行完之后调用
第二个参数,布尔值,当为true的时候,组件实例销毁后onAction依然存活
pinia和vuex都有一个共同的问题:当刷新页面之后,数据就消失了(恢复原始数据,之前的操作不会保留)
返回值:
总之我们要实现这个插件我们需要每次修改值就给它存起来
pinia-plugin.ts
import {createPinia, PiniaPluginContext} from "pinia";
//引入pinia
export const store = createPinia()
type Options = {
key?: string
}
//如果use.store(piniaPlugin)这样,没有传参数,就使用这个值作为key
const __piniaKey__: string = 'zhoubao'
//设置缓存的方法
const setStorage = (key: string, value: any) => {
localStorage.setItem(key, JSON.stringify(value))
}
//获取缓存的方法
const getStorage = (key: string) => {
return localStorage.getItem(key) ? JSON.parse(localStorage.getItem(key) as string) : {}
}
//pinia插件
//函数柯里化,概念看不太懂
//我们如果不使用这个技术,那么我们每次使用这个函数,就必须传入两个参数,但是我们发现,第二个参数都是一样的context: PiniaPluginContext
//所以我们希望这个函数只需要有一个参数,就是key,如果我们返回一个函数,而这个函数的形参为context: PiniaPluginContext
//那么我们发现,我们这个函数只需要传入一个参数就可以了
export const piniaPlugin = (options: Options) => {
return (context: PiniaPluginContext) => {
//context中是当前pinia的实例,我们通过解构的方式来获取其中我们需要存储的部分,也就是store
const {store} = context
//获取缓存中存储的store数据
const data = getStorage(`${options?.key ?? __piniaKey__}-${store.$id}`)
//pinia的api,当state中数据改变的时候,就设置缓存,设置缓存的时候需要toRaw方法(将refImpl对象转化为普通对象)才能正确放进去
store.$subscribe(() => {
setStorage(`${options?.key ?? __piniaKey__}-${store.$id}`, toRaw(store.$state))
})
//返回缓存中的数据,将store中的数据设置为缓存的数据
return {
...data
}
}
}
如果将pinia-plugin.ts中的代码全部放在main.ts中,代码太多了,不太行,我们将它分解出来,放在pinia-plugin.ts里面,暴露store对象以及piniaPlugin方法,最后再main.ts中使用store身上的use方法将piniaPlugin方法加载上去即可
npm安装 npm i pinia-plugin-persistedstate
vue3中使用:
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
import {createPinia} from "pinia";
//使用pinia数据持久化
const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)
createApp(App).use(ElementPlus).use(router).use(pinia).mount('#app')
使用方法
getters:{},
// 持久化
persist:{
key:'terminal-config-store',
storage:window.localStorage,
beforeRestore:()=>{
console.log("load terminalConfigStore data start");
},
afterRestore:()=>{
console.log("load terminalConfigStore data end")
}
},