pinia学习
01 - pinia介绍
Pinia.js 有如下特点:
完整的 ts 的支持;
足够轻量,压缩后的体积只有1kb左右;
去除 mutations,只有 state,getters,actions;
actions 支持同步和异步;
代码扁平化没有模块嵌套,只有 store 的概念,store 之间可以自由使用,每一个store都是独立的
无需手动添加 store,store 一旦创建便会自动添加;
支持Vue3 和 Vue2
起步安装
引入注册Vue3
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 hook创建
import { defineStore } from "pinia"; import {Names} from "./store-name"
export const useTestStore = defineStore(Names.TEST, { state: () => { return { name:'小潘', age:22 }; }, getters:{
}, actions:{ } });
|
store hook 使用
<template> <div> {{ testStore.name}}=={{ testStore.age }} </div> </template>
<script setup lang="ts"> import {useTestStore} from "./store"
const testStore = useTestStore() </script>
<style scoped>
</style>
|
02 - state使用的方式
第一种方式:直接使用
第二种方式:通过$patch,(可以传值一个或多个)
testStore.$patch({ age:19, name:"xiaopan" })
|
第三种方式:通过$patch,(可以传函数)(推荐使用)
testStore.$patch((state)=>{ state.age = 19 state.name = "xiaopan" })
|
第四种方式:通过$state,(只能传全部)
testStore.$state = { age:19, name:"xiaopan" }
|
第五种方式:通过action进行处理逻辑
testStore.updateAge(20)
actions:{ updateAge(age:number){ this.age = age } }
|
03 - 解构操作导致响应式问题
错误示范:
<template> <div> {{ testStore.name}}=={{ testStore.age }} <button @click="handleClick">改变</button> </div> </template>
<script setup lang="ts"> import {useTestStore} from "./store" const testStore = useTestStore()
let {name,age} = testStore const handleClick = ()=>{ // 这样会导致响应式丢失 name = 'xiaopan' age = 18 } </script>
<style scoped>
</style>
|
使用storeToRefs解决响应式丢失问题
使用storeToRefs将store中的状态变成Ref响应式进行操作的,这样就相当重新绑定了响应式。
<template> <div> {{ testStore.name}}=={{ testStore.age }} <button @click="handleClick">改变</button> </div> </template>
<script setup lang="ts"> import {useTestStore} from "./store" import {storeToRefs} from "pinia" const testStore = useTestStore()
let {name,age} = storeToRefs(testStore) const handleClick = ()=>{ name.value = 'xiaopan' age.value = 18 } </script>
<style scoped>
</style>
|
04 - getters 和 actions 使用
// app.vue
<template> <div> <div>action(异步):{{ user.name }} -- {{ user.age }}</div> <hr> <div>getter:{{ getUser.name }} === {{ getUser.age }}</div> <hr> <button @click="handleClick">点我更新</button> </div> </template>
<script setup lang="ts"> import {useTestStore} from "./store" import {storeToRefs} from "pinia" const testStore = useTestStore() const {user,getUser} = storeToRefs(testStore)
const handleClick = ()=>{ testStore.aysncUpdateAge() } </script>
<style scoped>
</style>
|
import { defineStore } from "pinia"; import {Names} from "./store-name"
interface User{ name:string age:number } const user = { name:'张三', age:18 }
const ProUSer = ():Promise<User>=>{ return new Promise((resolve)=>{ setTimeout(()=>{ resolve(user) },2000) }) }
export const useTestStore = defineStore(Names.TEST, { state: () => { return { user:{} as User }; }, getters:{ getUser():User{ return this.user } }, actions:{ async aysncUpdateAge(){ this.user = await ProUSer() } } });
|
05 - 实例API
$reset:重置store到他的初始状态
$subscribe:类似于Vuex 的abscribe 只要有state 的变化就会走这个函数
Test.$subscribe((args,state)=>{ console.log(args,state); })
|
$onAction:只要有actions被调用就会走这个函数
testStore.$onAction((args)=>{ console.log(args); })
|
06 - pinia持久化插件编写
import PiniaPlugin from "./store/plugins" const store = createPinia() store.use(piniaPlugin({key:'xiaopan'}))
import {PiniaPluginContext} from "pinia"
import { toRaw } from "vue";
const _PLUGINKEY_ = "_PLUGINKEY_"
interface OPtions { key?: string; }
const getValue = (key:string)=>{ return (localStorage.getItem(key)?JSON.parse(localStorage.getItem(key) as string):{}) }
const setValue = (key:string,value:any)=>{ localStorage.setItem(key,JSON.stringify(value)); }
const piniaPlugin = (options: OPtions) => { return (context:PiniaPluginContext) => { const {store} = context let data = getValue(`${options.key?options.key+store.$id:_PLUGINKEY_ + store.$id}`) context.store.$subscribe(()=>{ setValue(`${options.key?options.key+store.$id:_PLUGINKEY_ + store.$id}`,toRaw(store.$state)) }) return { ...data, }; }; };
export default piniaPlugin;
|