Pinia
Vue3中使用Pinia替代vuex
更改如下:
- 支持ts
- 体积小,压缩后1KB
- 去除 mutations,只有 state,getters,actions;
- 去除mutations后,actions 直接进行同步和异步操作修改数据
- 去除modules概念,只有store概念,每个store都是独立的
- 无需手动添加store,一旦创建则会自动添加
安装 npm i pinia
Vue3中注册pinia
import { createApp } from 'vue'
import App from './App.vue'
import {createPinia} from 'pinia'
const store = createPinia()
let app = createApp(App)
app.use(store)
app.mount('#app')
初试化仓库store
1.新建两个文件
src/store/store-name.ts
负责抽离仓库名字,管理仓库名字
export const enum Names {
Test1 = 'TEST1'
Test2 = 'TEST2'
Test3 = 'TEST3'
}
src/store/index.ts
store仓库核心代码
// defineStore()为定义仓库,第一个参数为仓库的ID,第二个参数仓库对象
import { defineStore } from 'pinia'
import { Names } from './store-name'
// 仓库名字定义为useXXX
export const useTestStore = defineStore(Names.Test1, {
// 提示可知state必须是箭头函数类型(actions和getters为对象)
state:()=>{
return {
current:1
}
},
//类似于computed 可以帮我们去修饰我们的值
getters:{
},
//可以操作异步 和 同步提交state,无需mutations
actions:{
}
})
在组件中利用使用以下五种方法修改
import { useTestStore } from "./store";
const Test = useTestStore()
- 直接修改state
Test.current++
- 仓库实例$patch方法批量修改
Test.$patch({
current:9,
name:'a'
})
- 仓库实例$patch方法批量修改,函数形式
Test.$patch((state)=>{
state.current = 10
state.name = 'b'
})
- 仓库实例$state替换整个实例,必须修改所有书序
Test.$state = {
current:2000,
name:'小满娃娃'
}
- 通过actions修改
// 仓库里acitons定义方法
actions:{
setCurrent(num:number){
this.current = num
}
}
// 组件直接调用
Test.setCurrent(567)
解构store
直接解构store里的属性,将会失去响应性
const Test = useTestStore()
const { current, name } = Test
console.log(current, name);
可以在解构前给仓库包裹一层storeToRefs()
import { storeToRefs } from 'pinia'
const Test = useTestStore()
const { current, name } = storeToRefs(Test)
Actions,getters
Actions同步调用
import { defineStore } from 'pinia'
import { Names } from './store-naspace'
export const useTestStore = defineStore(Names.TEST, {
state: () => ({
counter: 0,
}),
actions: {
increment() {
this.counter++
},
randomizeCounter() {
this.counter = Math.round(100 * Math.random())
},
},
})
<template>
<div>
<button @click="Add">+</button>
<div>
{{Test.counter}}
</div>
</div>
</template>
<script setup lang='ts'>
import {useTestStore} from './store'
const Test = useTestStore()
const Add = () => {
Test.randomizeCounter()
}
</script>
Actions异步调用,结合async 和 await
import { defineStore } from 'pinia'
import { Names } from './store-naspace'
type Result = {
name: string
isChu: boolean
}
const Login = (): Promise<Result> => {
return new Promise((resolve) => {
setTimeout(() => {
resolve({
name: '小满',
isChu: true
})
}, 3000)
})
}
export const useTestStore = defineStore(Names.TEST, {
state: () => ({
user: <Result>{},
name: "123"
}),
actions: {
async getLoginInfo() {
const result = await Login()
this.user = result;
}
},
})
<template>
<div>
<button @click="Add">test</button>
<div>
{{Test.user}}
</div>
</div>
</template>
<script setup lang='ts'>
import {useTestStore} from './store'
const Test = useTestStore()
const Add = () => {
Test.getLoginInfo()
}
</script>
多个actions调用
state: () => ({
user: <Result>{},
name: "default"
}),
actions: {
async getLoginInfo() {
const result = await Login()
this.user = result;
this.setName(result.name)
},
setName (name:string) {
this.name = name;
}
},
getters的作用类似于computed数据修饰并且有缓存
使用箭头函数不能使用this,请使用state
getters:{
newPrice:(state)=> `$${state.user.price}`
},
普通函数形式使用this
getters:{
newCurrent ():number {
return ++this.current
}
},
getters互相调用
getters:{
newCurrent ():number | string {
return ++this.current + this.newName
},
newName ():string {
return `$-${this.name}`
}
},
API
$reset,重置store到初始状态
state: () => ({
user: <Result>{},
name: "default",
current:1
})
const change = () => {
Test.current++
}
const change = () => {
Test.$reset()
}
订阅state的改变,只要有state 的变化就会走这个函数
Test.$subscribe((args,state)=>{
console.log(args,state);
})
如果你的组件卸载之后还想继续调用请设置第二个参数
Test.$subscribe((args,state)=>{
console.log(args,state);
},{
detached:true
})
订阅Actions的调用, 只要有actions被调用就会走这个函数
Test.$onAction((args)=>{
console.log(args);
})
pinia持久化插件
pinia 和 vuex 都有一个通病 页面刷新状态会丢失
const __piniaKey = '__PINIAKEY__'
//定义兜底变量
type Options = {
key?:string
}
//定义入参类型
//将数据存在本地
const setStorage = (key: string, value: any): void => {
localStorage.setItem(key, JSON.stringify(value))
}
//存缓存中读取
const getStorage = (key: string) => {
return (localStorage.getItem(key) ? JSON.parse(localStorage.getItem(key) as string) : {})
}
//利用函数柯丽华接受用户入参
const piniaPlugin = (options: Options) => {
//将函数返回给pinia 让pinia 调用 注入 context
return (context: PiniaPluginContext) => {
const { store } = context;
const data = getStorage(`${options?.key ?? __piniaKey}-${store.$id}`)
store.$subscribe(() => {
setStorage(`${options?.key ?? __piniaKey}-${store.$id}`, toRaw(store.$state));
})
//返回值覆盖pinia 原始值
return {
...data
}
}
}
//初始化pinia
const pinia = createPinia()
//注册pinia 插件
pinia.use(piniaPlugin({
key: "pinia"
}))
标签:const,name,state,pinia,Vue3,Test,store
From: https://www.cnblogs.com/wanglei1900/p/16769572.html