Pinia
Vue 专属状态管理库, 可以跨组件或页面共享状态.
- 测试工具集
- 插件
- 自动补全功能
- 支持服务端渲染
- Devtools 支持
- 热更新
Store
store 是一个保存状态和业务逻辑的实体, 并不与组件树绑定.
像一个永远存在的组件, 每个组件都可以读取和写入它.
三个概念
- state 类比 vue 的 data
- getter 类比 vue 的 computed
- action 类比 vue 的 methods
什么时候使用 Store ?
一个 Store 应该包含在整个应用中访问的数据. 应该避免引入原本可以在组件中保存的本地数据.
定义 Store
你应该在不同的文件中去定义 store。 (为了 typescript 推断, 构建工具进行代码分割等.)
export const useAlertsStore = defineStore("alerts", {});
- 返回值建议使用 use 开头, Store 结尾的格式进行命名
- 第一个参数为 Store 的Id, 需全局唯一
- 第二个参数为 Setup 函数或 Option 对象
Option Store: 传入带有 state, actions, getters 属性的 Option 对象.
export const useCounterStore = defineStore("counter", {
// data 数据
state: () => ({ count: 0 }),
// computed 计算数学
getters: {
double: (state) => state.count * 2,
},
// methods 方法
actions: {
increment() {
this.count++;
},
},
});
Setup Store: 传入一个 Setup 箭头函数.
export const useCounterStore = defineStore("counter", () => {
const count = ref(0);
const name = ref("wangzhy");
const doubleCount = computed(() => count.value * 2);
function increment() {
count.value++;
}
return { count, name, doubleCount, increment };
});
对应关系:
ref --> data
computed() --> getters
function() --> actions
Setup Store 需要返回 state 的所有属性
要让 pinia 正确识别 state,你必须在 setup store 中返回 state 的所有属性。这意味着,你不能在 store 中使用私有属性。
需要将所有通过 ref 定义的 state 进行显式返回. 否则 Pinia 无法将其识别为响应式状态.
pinia Setup Store 可以在 inject 中使用 app.provide 提供的数据.
import { inject } from "vue";
import { useRoute } from "vue-router";
import { defineStore } from "pinia";
export const useSearchFilters = defineStore("search-filters", () => {
const route = useRoute();
// 这里假定 `app.provide('appProvided', 'value')` 已经调用过
const appProvided = inject("appProvided");
// ...
return {
// ...
};
});
需要注意的是,不要在 Setup Store 中将 appProvided 进行返回. 因为这并不是 Store 的东西.
使用 Store
import { useCounterStore } from "@/stores/counter";
const counter = useCounterStore();
Store 是一个用 reactive 包装的对象, 这意味着不需要在 getters 后面写 .value.就像 setup 中的 props 一样, 不能对 store 解构
从 Store 解构: storeToRefs()
data, getters 需要通过 storeToRefs() 进行解构.
actions 可以直接进行解构.
import { useCounterStore } from "@/stores/counter";
import { storeToRefs } from "pinia";
const counter = useCounterStore();
// storeToRefs 会跳过所有的 actions 和非响应式(即非ref/非reactive)属性
const { count } = storeToRefs(counter);
const { increment } = counter;