介绍
Pinia是一个Vue的状态管理库,可以用于在应用程序中管理状态。
安装
yarn add pinia
#or
npm install pinia。
使用
1.在main.js文件中导入Pinia,并将其添加到我们的应用程序中
//main.js
import { createPinia } from 'pinia'
const pinia = createPinia()
const app = createApp(App)
app.use(pinia).mount('#app')
- 创建一个名为ProductStore的存储器,并定义其初始状态和获取器
import { defineStore } from 'pinia'
//const useProductStore = defineStore('product', {}),其中的product为pinia的id,确保唯一性;命名一般使用useXXX,如useProductStore
export const useProductStore = defineStore('product', {
state: () => ({
products: [ Product1,Product2,Product3];
current:0;
name:"物品"
}),
//类似于computed 可以帮我们去修饰我们的值
getters: {
productCount(state) {
// 获取器可以访问状态
return state.products.length
},
productsCheaperThan(state, price) {
// 获取器可以接受参数
return (product) => {
// 获取器必须返回一个函数而不是一个布尔值
return product.price < price
}
}
},
//可以操作异步 和 同步提交state
actions: {
addProduct(Product) {
this.products.push(Product)
},
setCurrent () {
this.current++
}
}
})
修改state值的几种方法
import {useProductStore} from './store'
const product = useProductStore()
//1.直接修改,State 是允许直接修改值
const Add = () => {
product.current++
}
//2.使用$patch修改State的值,$patch方法可以批量修改多个值
const Add = () => {
product.$patch({
current:200,
name:"食品"
})
}
//3.批量修改函数形式;推荐使用
const Add = () => {
product.$patch((state)=>{
state.current++;
state.name="食品"
})
}
//通过原始对象修改整个实例
//使用$state方法,即:通过将store的属性设置为新对象来替换store的整个状态;缺点:必须修改整个对象的所有属性
const Add = () => {
Test.$state = {
current:10,
name:"食品"
}
}
//5.通过action方法修改state的值
const Add = () => {
product.setCurrent()
}
然后,我们可以在Vue组件中使用这个存储器。有两种方法可以使用Pinia: Composition API 和 Options API。
对于 Composition API,我们可以在组件的<script setup>
块中导入并使用存储器实例
<template>
<ul>
<li v-for="product in store.products">{{ product }}</li>
</ul>
<p>{{ store.productCount }}</p>
<ul>
<li v-for="product in store.productsCheaperThan(10)">{{ product }}</li>
</ul>
<button @click="store.addProduct(Product)">Add</button>
</template>
<script setup>
import { useProductStore } from "./stores/ProductStore";
const store = useProductStore();
</script>
对于 Options API,我们可以在组件的<script>
块中导入存储器,并使用mapStores函数将其映射到计算属性上:
<template>
<ul>
<li v-for="product in productStore.products">{{ product }}</li>
</ul>
<p>{{ productStore.productCount }}</p>
<ul>
<li v-for="product in productStore.productsCheaperThan(10)">
{{ product }}
</li>
</ul>
<button @click="productStore.addProduct(Product)">Add</button>
</template>
<script>
import { useProductStore } from "./stores/ProductStore";
import { mapStores } from "pinia";
export default {
// 导入 mapStores 函数
setup() {
// 映射存储器到计算属性上
return {
...mapStores(useProductStore),
// 计算属性
someComputed() {
// 使用存储器中的数据
},
};
},
};
</script>
pinia的API
$reset
$reset,重置store
到他的初始状态
// 恢复初始状态
store.$reset()
$subscribe
我们还可以订阅存储器的变化并在变化后执行某些操作:
只要有state 的变化就会走这个函数
store.$subscribe((mutation, state) => {
console.log(`State changed: ${JSON.stringify(state)}`)
})
$onAction
订阅Actions的调用,只要有actions被调用就会走这个函数
store.$onAction((args)=>{
console.log(args);
})
【拓展】利用localStorage实现pinia持久化并封装组件
(具体的使用场景我还没有用到,觉得有用,先记录下来)
// src/utils/piniaPlugin.js
import { toRaw } from 'vue'
const setStorage = (key, value) => {
localStorage.setItem(key, JSON.stringify(value))
}
//存缓存中读取
const getStorage = (key) => {
return (localStorage.getItem(key) ? JSON.parse(localStorage.getItem(key)) : {})
}
const piniaPlugin = (option) => {
return (context) => {
const { store } = context
const data = getStorage(`${option.key}-${store.$id}`)
store.$subscribe(() => {
setStorage(`${option.key}-${store.$id}`, toRaw(store.$state));
})
return {
...data
}
}
}
export default piniaPlugin
//main.js
import { createPinia } from 'pinia'
import { createApp } from 'vue'
import App from './App.vue'
import './assets/main.css'
import piniaPlugin from './utils/piniaPlugin.js' // 引入封装好的插件
const pinia = createPinia()
pinia.use(piniaPlugin( { key: "pinia" }))
const app = createApp(App)
app.use(pinia)
.mount('#app')
后续慢慢完善……
参考:
pinia插件