Skip to content

Pinia 与 Vuex 对比

Pinia 起源于对 Vuex 下一代的探索,融合了 Vuex 5 设计讨论中的诸多理念。Pinia 已经实现了我们在 Vuex 5 期望的大部分功能,因此成为官方推荐的状态管理方案,逐步取代 Vuex。

Pinia 相比 Vuex,拥有更简洁的 API、更好的组合式 API 支持,以及更优秀的 TypeScript 类型推断体验。


主要区别一览

功能VuexPinia
安装npm install vuexnpm install pinia
创建 StorecreateStore({ ... })createPinia()
挂载app.use(store)app.use(pinia)
定义 Storemodulesstore/index.jsdefineStore('name', { ... })
访问 Statestore.state.xxxuseStore().xxx
Gettersstore.getters.xxxuseStore().xxx(直接作为属性访问)
Mutationsstore.commit('mutation')直接修改 state 或通过 action
Actionsstore.dispatch('action')useStore().action()
Modulesmodules: { ... }多个 store 文件,自动模块化
TypeScript支持一般,需要手动类型声明类型推断优秀,几乎无需手动声明
组合式 API支持有限完全支持

vuex 转换 Pinia

Pinia 的设计目标是简化 Vuex 的使用方式,提供更直观的 API。以下是一些常见的转换示例:

参考:vuex-to-pinia

注意事项:

  • Pinia 不再使用 getters,而是直接将计算属性作为 store 的属性。
  • Pinia 的 actions 可以直接修改 state,无需使用 commit
  • Pinia 的 actions 可以返回 Promise,用于异步操作。
  1. store 添加一个必要的 id,你可以让它与之前的命名保持相同。

  2. 如果 state 不是一个函数的话 将它转换为一个函数。

  3. mutations 转换为 actions

    • Mutation 已经被弃用了。它们可以被转换为 action,或者你可以在你的组件中直接赋值给 store (例如:userStore.firstName = 'First')
    • 如果你想将它转换为 action,删除第一个 state 参数,用 this 代替任何赋值操作中的 state。
    • 一个常见的 mutation 是将 state 重置为初始 state。而这就是 store 的 $reset 方法的内置功能。注意,这个功能只存在于 option stores。
  4. 转换 actions

    • Actions 可以直接修改 state,无需使用 commit
    • Actions 可以返回 Promise,用于异步操作。
    • Actions 从每个 action 中删除第一个 context 参数。所有的东西都应该直接从 this 中访问可以使用 this 访问 state 和其他 actions。
  5. 转行 getters:

    • Pinia 不再使用 getters,而是直接将计算属性作为 store 的属性。
    • 你可以直接在组件中使用这些计算属性。

代码对比示例

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;

参考

Released Under The MIT License.