Appearance
Pinia 与 Vuex 对比
Pinia 起源于对 Vuex 下一代的探索,融合了 Vuex 5 设计讨论中的诸多理念。Pinia 已经实现了我们在 Vuex 5 期望的大部分功能,因此成为官方推荐的状态管理方案,逐步取代 Vuex。
Pinia 相比 Vuex,拥有更简洁的 API、更好的组合式 API 支持,以及更优秀的 TypeScript 类型推断体验。
主要区别一览
| 功能 | Vuex | Pinia |
|---|---|---|
| 安装 | npm install vuex | npm install pinia |
| 创建 Store | createStore({ ... }) | createPinia() |
| 挂载 | app.use(store) | app.use(pinia) |
| 定义 Store | modules 或 store/index.js | defineStore('name', { ... }) |
| 访问 State | store.state.xxx | useStore().xxx |
| Getters | store.getters.xxx | useStore().xxx(直接作为属性访问) |
| Mutations | store.commit('mutation') | 直接修改 state 或通过 action |
| Actions | store.dispatch('action') | useStore().action() |
| Modules | modules: { ... } | 多个 store 文件,自动模块化 |
| TypeScript | 支持一般,需要手动类型声明 | 类型推断优秀,几乎无需手动声明 |
| 组合式 API | 支持有限 | 完全支持 |
vuex 转换 Pinia
Pinia 的设计目标是简化 Vuex 的使用方式,提供更直观的 API。以下是一些常见的转换示例:
参考:vuex-to-pinia;
注意事项:
- Pinia 不再使用
getters,而是直接将计算属性作为 store 的属性。 - Pinia 的
actions可以直接修改 state,无需使用commit。 - Pinia 的
actions可以返回 Promise,用于异步操作。
store 添加一个必要的 id,你可以让它与之前的命名保持相同。
如果 state 不是一个函数的话 将它转换为一个函数。
将
mutations转换为actions。- Mutation 已经被弃用了。它们可以被转换为 action,或者你可以在你的组件中直接赋值给 store (例如:userStore.firstName = 'First')
- 如果你想将它转换为 action,删除第一个 state 参数,用 this 代替任何赋值操作中的 state。
- 一个常见的 mutation 是将 state 重置为初始 state。而这就是 store 的 $reset 方法的内置功能。注意,这个功能只存在于 option stores。
转换
actions:- Actions 可以直接修改 state,无需使用
commit。 - Actions 可以返回 Promise,用于异步操作。
- Actions 从每个 action 中删除第一个 context 参数。所有的东西都应该直接从 this 中访问可以使用
this访问 state 和其他 actions。
- Actions 可以直接修改 state,无需使用
转行
getters:- Pinia 不再使用
getters,而是直接将计算属性作为 store 的属性。 - 你可以直接在组件中使用这些计算属性。
- Pinia 不再使用
代码对比示例
1. 创建 Store
Vuex
js
// store/index.js
import { createStore } from "vuex";
export default createStore({
state: () => ({ count: 0 }),
mutations: {
increment(state) {
state.count++;
},
},
actions: {
increment({ commit }) {
commit("increment");
},
},
});Pinia
js
// stores/counter.js
import { defineStore } from "pinia";
export const useCounterStore = defineStore("counter", {
state: () => ({ count: 0 }),
actions: {
increment() {
this.count++;
},
},
});2. 在组件中使用
Vuex
js
import { useStore } from "vuex";
import { computed } from "vue";
const store = useStore();
const count = computed(() => store.state.count);
const increment = () => store.commit("increment");Pinia
js
import { useCounterStore } from "@/stores/counter";
const counter = useCounterStore();
const count = computed(() => counter.count);
const increment = counter.increment;