跳转到内容

Vuex状态管理

来自代码酷
Admin留言 | 贡献2025年5月12日 (一) 00:25的版本 (Page creation by admin bot)

(差异) ←上一版本 | 已核准修订 (差异) | 最后版本 (差异) | 下一版本→ (差异)


VuexVue.js 的官方状态管理库,用于集中式存储和管理应用的所有组件的状态。它采用单向数据流模式,确保状态变更可预测且易于调试,特别适合中大型单页应用(SPA)。

核心概念[编辑 | 编辑源代码]

状态(State)[编辑 | 编辑源代码]

Vuex 使用单一状态树(Single State Tree)存储整个应用的状态,相当于组件的 "data" 但全局共享。

const store = new Vuex.Store({
  state: {
    count: 0,
    user: { name: 'Alice' }
  }
})

获取状态[编辑 | 编辑源代码]

组件通过 this.$store.statemapState 辅助函数访问状态:

// 选项式API
computed: {
  count() {
    return this.$store.state.count
  }
}

// 组合式API
import { computed } from 'vue'
import { useStore } from 'vuex'

const store = useStore()
const count = computed(() => store.state.count)

变更状态(Mutations)[编辑 | 编辑源代码]

唯一修改状态的方式是提交 mutation(同步操作):

mutations: {
  increment(state, payload) {
    state.count += payload.amount
  }
}

// 组件中调用
this.$store.commit('increment', { amount: 10 })

异步操作(Actions)[编辑 | 编辑源代码]

Action 通过提交 mutation 间接变更状态,可包含任意异步操作:

actions: {
  async fetchUser({ commit }, userId) {
    const user = await api.getUser(userId)
    commit('SET_USER', user)
  }
}

// 组件中调用
this.$store.dispatch('fetchUser', 'user123')

派生状态(Getters)[编辑 | 编辑源代码]

相当于 store 的计算属性:

getters: {
  doubleCount: (state) => state.count * 2,
  filteredTodos: (state) => (status) => {
    return state.todos.filter(todo => todo.status === status)
  }
}

// 使用
this.$store.getters.doubleCount
this.$store.getters.filteredTodos('completed')

数据流图示[编辑 | 编辑源代码]

graph LR A[组件] -->|dispatch| B(Action) B -->|commit| C(Mutation) C -->|mutate| D(State) D -->|render| A

模块化(Modules)[编辑 | 编辑源代码]

大型应用可将 store 分割为模块:

const userModule = {
  namespaced: true,
  state: () => ({ profile: {} }),
  mutations: { /* ... */ }
}

const store = new Vuex.Store({
  modules: {
    user: userModule
  }
})

// 访问模块状态
this.$store.state.user.profile

实际案例[编辑 | 编辑源代码]

电商购物车实现

// store.js
export default new Vuex.Store({
  state: {
    cartItems: [],
    inventory: {}
  },
  mutations: {
    ADD_TO_CART(state, product) {
      const item = state.cartItems.find(i => i.id === product.id)
      item ? item.quantity++ : state.cartItems.push({ ...product, quantity: 1 })
    }
  },
  actions: {
    async loadInventory({ commit }) {
      const products = await fetch('/api/products')
      commit('SET_INVENTORY', products)
    }
  },
  getters: {
    cartTotal: state => {
      return state.cartItems.reduce((sum, item) => 
        sum + (item.price * item.quantity), 0)
    }
  }
})

与Pinia的对比[编辑 | 编辑源代码]

Vuex 4.x 与 Pinia(Vuex 的替代方案)主要区别:

特性 Vuex Pinia
Vue 版本 2.x/3.x 3.x+
类型支持 需要额外配置 开箱即用
模块系统 需要命名空间 自动命名空间
语法复杂度 较高 更简洁

最佳实践[编辑 | 编辑源代码]

1. 遵循单一职责原则拆分模块 2. 使用常量命名 mutation 类型 3. 表单处理建议:

   // 使用双向绑定+计算属性
   computed: {
     message: {
       get() { return this.$store.state.obj.message },
       set(value) { this.$store.commit('UPDATE_MESSAGE', value) }
     }
   }

数学表达[编辑 | 编辑源代码]

状态更新可表示为: σt+1=M(σt,a) 其中:

  • σ 为状态
  • M 为 mutation 函数
  • a 为 action 负载

常见问题[编辑 | 编辑源代码]

Q: 何时该用 Vuex? A: 当多个组件需要共享状态或存在深层次组件通信时。

Q: 可以直接修改 state 吗? A: 严格模式下会报错,必须通过 mutation 修改。

模板:Vue.js相关主题