Vue 3 中,Pinia 和 Vuex 的主要区别

发布于:2025-02-18 ⋅ 阅读:(157) ⋅ 点赞:(0)

总结对比表

对比项 Vuex Pinia
API 设计 区分 mutations/actions state/actions/getters
模块化 嵌套式配置 独立 Store,按需组合
TypeScript 需手动声明类型 原生自动推断
代码简洁性 冗余(需 commit/dispatch 直接调用方法
推荐场景 Vue 2 升级项目/严格规范 Vue 3 新项目/灵活简洁

Vue 3 中 Pinia 和 Vuex 的核心区别及代码对比

1. 核心 API 对比

Vuex 示例
// store.js
import { createStore } from 'vuex';

export default createStore({
  state: {
    count: 0
  },
  mutations: {
    increment(state) {
      state.count++; // 必须通过 mutations 同步修改
    }
  },
  actions: {
    incrementAsync({ commit }) {
      setTimeout(() => {
        commit('increment'); // 异步操作需调用 commit
      }, 1000);
    }
  },
  getters: {
    doubleCount: (state) => state.count * 2
  }
});
Pinia 示例
// counterStore.js
import { defineStore } from 'pinia';

export const useCounterStore = defineStore('counter', {
  state: () => ({ count: 0 }),
  actions: {
    increment() {
      this.count++; // 直接通过 this 修改状态
    },
    async incrementAsync() {
      setTimeout(() => {
        this.increment(); // 支持异步操作
      }, 1000);
    }
  },
  getters: {
    doubleCount: (state) => state.count * 2
  }
});

关键差异

  • Pinia 移除 mutations,允许在 actions 中直接修改状态(同步/异步均可)。
  • Vuex 强制区分 mutations(同步)和 actions(异步)。

2. 模块化对比

Vuex 模块化(嵌套式)
// userModule.js
export default {
  state: { name: 'User' },
  mutations: { ... }
};

// store.js
import userModule from './userModule';

export default createStore({
  modules: {
    user: userModule // 嵌套式模块
  }
});
Pinia 模块化(扁平化)
// userStore.js
export const useUserStore = defineStore('user', {
  state: () => ({ name: 'User' })
});

// productStore.js
export const useProductStore = defineStore('product', { ... });

关键差异

  • Vuex 需在单一 Store 中嵌套模块;Pinia 支持独立定义 Store,按需引入。

3. 组件中使用对比

Vuex 组件调用
<template>
  <div>{{ $store.state.count }}</div>
  <button @click="$store.commit('increment')">同步 +1</button>
  <button @click="$store.dispatch('incrementAsync')">异步 +1</button>
</template>
Pinia 组件调用
<template>
  <div>{{ counterStore.count }}</div>
  <button @click="counterStore.increment()">同步 +1</button>
  <button @click="counterStore.incrementAsync()">异步 +1</button>
</template>

<script setup>
import { useCounterStore } from './counterStore';
const counterStore = useCounterStore();
</script>

关键差异

  • Pinia 通过 Store 实例直接调用方法,代码更简洁;Vuex 需通过 commit/dispatch

4. TypeScript 支持对比

Vuex 类型声明(手动)
// 需手动定义类型
interface State {
  count: number;
}

const store = createStore<State>({
  state: { count: 0 },
  mutations: {
    increment(state) {
      state.count++; // 需手动确保类型匹配
    }
  }
});
Pinia 类型推断(自动)
// 自动推断类型
const counterStore = useCounterStore();
counterStore.increment(); // 方法名和参数自动提示
counterStore.count++;     // 直接修改状态(需配置允许)

关键差异

  • Pinia 原生支持 TypeScript 类型推断;Vuex 需手动配置类型。

5. 响应式解构对比

Pinia 的响应式解构
import { storeToRefs } from 'pinia';

const counterStore = useCounterStore();
const { count, doubleCount } = storeToRefs(counterStore); // 解构后仍保持响应式

Vuex 的局限性

  • Vuex 解构 $store.state.count 会失去响应性,需通过 computed 包装。

总结对比表

对比项 Vuex Pinia
API 设计 区分 mutations/actions state/actions/getters
模块化 嵌套式配置 独立 Store,按需组合
TypeScript 需手动声明类型 原生自动推断
代码简洁性 冗余(需 commit/dispatch 直接调用方法
推荐场景 Vue 2 升级项目/严格规范 Vue 3 新项目/灵活简洁

网站公告

今日签到

点亮在社区的每一天
去签到