Pinia 与 Vuex 在 Vue 3 中的使用区别

193 阅读2分钟

Pinia 与 Vuex 在 Vue 3 中的使用区别

本篇文章面向各位前端Vuer初学者,重点介绍在 Vue 3 中使用 Pinia 与 Vuex 的差异,主要在日常使用上区分一下


一、状态定义方式对比

1. Vuex 定义方式

Vuex 的状态管理采用集中式设计,核心包括 stategettersmutationsactions

// store/index.js
import { createStore } from 'vuex'

export const store = createStore({
  state: () => ({
    count: 0
  }),
  getters: {
    doubleCount (state) {
      return state.count * 2
    }
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    asyncIncrement ({ commit }) {
      setTimeout(() => {
        commit('increment')
      }, 1000)
    }
  }
})
  • 所有状态变更必须通过 mutations 完成。
  • actions 用于异步操作,需通过 commit 调用 mutation。

2. Pinia中option 定义方式

Pinia option store 写法,使用 defineStore 定义每个 store,省略 mutation,直接在 action 中修改状态:

// stores/counter.js
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0
  }),
  getters: {
    doubleCount: (state) => state.count * 2
  },
  actions: {
    increment() {
      this.count++
    },
    asyncIncrement() {
      setTimeout(() => {
        this.increment()
      }, 1000)
    }
  }
})
  • 状态可直接通过 this 修改,无需 mutation。
  • actions 支持同步与异步处理,调用简单:counterStore.increment()

3. Pinia 中的组合式写法

Pinia 也支持更加灵活的组合式写法(setup store模式),更贴近 Vue 3 的风格:

// stores/counterSetup.js
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'

export const useCounterSetupStore = defineStore('counterSetup', () => {
  const count = ref(0)
  const doubleCount = computed(() => count.value * 2)

  function increment() {
    count.value++
  }

  return {
    count,
    doubleCount,
    increment
  }
})

使用组合式写法后,Pinia store 更像普通的 Vue 3 组合式逻辑,可与其他 Composition API 模块轻松组合。


二、模块化处理方式对比

1. Vuex 模块化

Vuex 通过 modules 属性集中注册子模块,结构树状、层级明确:

// store/modules/user.js
export const user = {
  namespaced: true,
  state: () => ({
    name: 'Alice'
  }),
  mutations: {
    setName (state, name) {
      state.name = name
    }
  },
  actions: {
    updateName({ commit }, name) {
      commit('setName', name)
    }
  }
}

// store/index.js
import { createStore } from 'vuex'
import { user } from './modules/user'

export const store = createStore({
  modules: {
    user
  }
})
  • 模块需统一集中注册。
  • 使用时需携带模块名访问:store.commit('user/setName', 'Bob')

2. Pinia 模块化

Pinia 中,每个 store 都是独立模块,不需集中注册,按需引入即可:

// stores/userStore.js
import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', {
  state: () => ({
    name: 'Alice'
  }),
  actions: {
    setName(name) {
      this.name = name
    }
  }
})

使用方式:

// 在组件中使用
const userStore = useUserStore()
userStore.setName('Bob')
  • 无需模块嵌套与命名空间问题。
  • 各模块按需导入,结构清晰、松耦合。

三、小结

对比点VuexPinia
状态定义方式需要配置 state / getters / mutations / actions可省略 mutation,支持 setup 风格
状态修改方式必须通过 commit可在 action 中直接修改 state
模块组织modules 统一注册独立模块,按需引入

总体来说,Pinia 在 Vue 3 项目中更符合组合式开发理念,API 简洁、类型友好,是目前 Vue 官方推荐的状态管理方案。