什么是Pinia?
vue的状态管理。
Pinia特点
- ts支持
- 轻量级 1kb+
- 没有mutations。
- actions 支持同步和异步
- 没有模块嵌套,只有 store 的概念,store 之间可以自由使用,更好的代码分割;
- 无需手动添加 store,store 一旦创建便会自动添加;
开发支持
- 时间旅行
- 追踪actions
- dev工具支持
热模块更新
- 在不重新加载页面的情况下修改存储
- 在开发过程中保持现有状态
引入
import { createPinia } from 'pinia'
app.use(createPinia())
定义Store
Define
import { defineStore } from "pinia";
export const useTestStore = defineStore("test", {
// options...
});
Using
<script setup>
import { useTestStore } from "@/store/test.js";
const store = useTestStore();
</script>
Tip
store是一个用reactive包装的对象,不要使用解构赋值获取状态。
<script setup>
import { useTestStore } from "@/store/test.js";
const store = useTestStore();
const { state1 , state2 } = store;
// state1,state2将去失去响应性
const state1 = computed(() => store.state1);
// yes
</script>
使用storeToRefs()提取状态
<script setup>
import { storeToRefs } from 'pinia'
import { useTestStore } from "@/store/test.js";
const store = useTestStore();
const { state1, state2 } = storeToRefs(store)
</script>
State
import { defineStore } from "pinia";
export const useTestStore = defineStore("test", {
state: () => {
return {
name: "Yomuki",
age: 16,
items: [],
};
},
});
Accessing
默认情况下,通过store实例访问状态,可以直接读取和写入。
const store = useStore()
store.age++
Resetting
通过调用存储区上的$reset()方法,可以将状态重置为初始值。
store.$reset()
Mutating
调用$patch方法,可对部分状态对象同时应用多个更改。
store.$patch({
age: store.age + 19,
name: '阿尔宙斯',
})
然而,使用这种语法应用某些突变非常困难或代价高昂:任何集合修改(例如,从数组中推、删除、拼接元素)都需要创建新集合。因此,$patch方法还接受一个函数,用于对难以应用于patch对象的此类突变进行分组。
store.$patch((state) => {
state.items.push({
id: 666,
name: "ZHENNIUBI",
});
});
Replacing
通过将存储的$state属性设置为新对象,可以替换存储的整个状态。
store.$state = { name: "这有啥用", age: 11 }
Subscribing
订阅状态变化。
与常规watch()相比,使用$subscribe()的优点是,在补丁之后,订阅只会触发一次。
const handleClick = () => {
store.$patch((state) => {
state.items.push({
id: 666,
name: "ZHENNIUBI",
});
});
store.age++;
};
store.$subscribe((mutation, state) => {
console.log(mutation, state);
});
默认情况下,状态订阅绑定到添加它们的组件(如果存储在组件的setup()中)。也就是说,当卸载组件时,它们将自动删除。如果要在卸载组件后保留它们,请将{detached:true}作为第二个参数传递,以从当前组件分离状态订阅。
someStore.$subscribe(callback, { detached: true })
可以在pinia实例上查看整个状态【没试过 记一下 防止忘了】
watch(
pinia.state,
(state) => {
// persist the whole state to the local storage whenever it changes
localStorage.setItem('piniaState', JSON.stringify(state))
},
{ deep: true }
)
Getters
Accessing
import { defineStore } from "pinia";
export const useTestStore = defineStore("test", {
state: () => {
return {
name: "Yomuki",
age: 16,
items: [],
};
},
getters: {
doubleAge: (state) => {
return state.age * 2;
},
},
});
other stores getters
import { useOtherStore } from './other-store'
export const useStore = defineStore('main', {
state: () => ({
// ...
}),
getters: {
otherGetter(state) {
const otherStore = useOtherStore()
return state.localData + otherStore.data
},
},
})
Passing arguments
传参
getters: {
getAgeTotal: (state) => {
return (age = 12) => state.age + age;
},
},
const store = useTestStore();
const getAgeTotal = store.getAgeTotal;
<template>
ageTotal : {{ getAgeTotal(99) }}
</template>
请注意,在执行此操作时,getter不再被缓存,它们只是您调用的函数。但是,您可以将一些结果缓存在getter本身中,这是不常见的,但应该证明更有效。
export const useStore = defineStore('main', {
getters: {
getActiveUserById(state) {
const activeUsers = state.users.filter((user) => user.active)
return (userId) => activeUsers.find((user) => user.id === userId)
},
},
})
Actions
写业务逻辑。支持异步。可访问other store
Accessing
import { defineStore } from "pinia";
export const useTestStore = defineStore("test", {
state: () => {
return {
name: "Yomuki",
age: 16,
items: [],
};
},
actions:{
increment() {
this.age++
},
async setUserInfo() {
try {
const { name, age } = await apiGetUserInfo();
this.name = name;
this.age = age;
} catch (err) {
console.error(err);
return err;
}
},
}
});
Subscribing
$onAction()观察行动及其结果。
默认情况下,当卸载组件时,它们将自动删除。如果要在卸载组件后保留它们,请将true作为第二个参数传递,以从当前组件分离操作订阅。
const unsubscribe = someStore.$onAction(
({
name, // name of the action
store, // store instance, same as `someStore`
args, // 入参array
after, // 结束钩子
onError, // err钩子 throws或Promise.reject
}) => {
after((result) => {
})
onError((error) => {
})
},
true // 在卸载组件后保留它们
)
// 手动删除侦听器
unsubscribe()
Plugins
大概率就需要个缓存数据的。