【DeepSeek帮我准备前端面试100问】(十一)vuex的使用

119 阅读2分钟

Vuex 使用详解

Vuex 是 Vue.js 的官方状态管理库,专为 Vue.js 应用程序开发的状态管理模式。下面我将全面介绍 Vuex 的核心概念、使用方法和最佳实践。

一、Vuex 核心概念

1. Vuex 架构图

┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│   Actions   │───>│  Mutations  │───>│    State    │
└─────────────┘    └─────────────┘    └─────────────┘
       ▲                                     │
       └─────────────────────────────────────┘

2. 五大核心概念

  1. State:应用状态数据源
  2. Getters:从 state 派生的计算属性
  3. Mutations:修改 state 的唯一途径(同步)
  4. Actions:提交 mutation,可包含异步操作
  5. Modules:将 store 分割成模块

二、基本使用

1. 安装与引入

npm install vuex --save
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    incrementAsync ({ commit }) {
      setTimeout(() => {
        commit('increment')
      }, 1000)
    }
  },
  getters: {
    doubleCount: state => state.count * 2
  }
})
// main.js
import store from './store'

new Vue({
  store,
  // ...其他配置
}).$mount('#app')

2. 在组件中使用

// 访问 state
this.$store.state.count

// 调用 mutation
this.$store.commit('increment')

// 调用 action
this.$store.dispatch('incrementAsync')

// 访问 getter
this.$store.getters.doubleCount

三、核心概念详解

1. State

定义:存储应用状态的单一数据源

state: {
  user: {
    name: 'John',
    age: 30
  },
  todos: []
}

组件中访问

// 直接访问
this.$store.state.user.name

// 使用 mapState 辅助函数
import { mapState } from 'vuex'

computed: {
  ...mapState(['user']),
  ...mapState({
    userName: state => state.user.name
  })
}

2. Getters

定义:基于 state 的计算属性

getters: {
  completedTodos: state => {
    return state.todos.filter(todo => todo.completed)
  },
  completedTodosCount: (state, getters) => {
    return getters.completedTodos.length
  }
}

组件中访问

// 直接访问
this.$store.getters.completedTodos

// 使用 mapGetters 辅助函数
import { mapGetters } from 'vuex'

computed: {
  ...mapGetters(['completedTodos']),
  ...mapGetters({
    doneTodos: 'completedTodos'
  })
}

3. Mutations

定义:修改 state 的唯一方法(同步)

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

组件中提交

// 直接提交
this.$store.commit('increment', { amount: 10 })

// 对象风格提交
this.$store.commit({
  type: 'increment',
  amount: 10
})

// 使用 mapMutations 辅助函数
import { mapMutations } from 'vuex'

methods: {
  ...mapMutations(['increment']),
  ...mapMutations({
    add: 'increment'
  })
}

4. Actions

定义:提交 mutation,可包含异步操作

actions: {
  async fetchUser ({ commit }, userId) {
    try {
      const user = await api.getUser(userId)
      commit('setUser', user)
    } catch (error) {
      commit('setError', error)
    }
  }
}

组件中分发

// 直接分发
this.$store.dispatch('fetchUser', { userId: 123 })

// 对象风格分发
this.$store.dispatch({
  type: 'fetchUser',
  userId: 123
})

// 使用 mapActions 辅助函数
import { mapActions } from 'vuex'

methods: {
  ...mapActions(['fetchUser']),
  ...mapActions({
    getUser: 'fetchUser'
  })
}

5. Modules

定义:将 store 分割成模块

const moduleA = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

命名空间

const moduleA = {
  namespaced: true,
  state: () => ({ ... }),
  // ...
}

// 访问命名空间模块
this.$store.state.a // -> moduleA 的状态
this.$store.getters['a/someGetter']
this.$store.commit('a/someMutation')
this.$store.dispatch('a/someAction')

// 辅助函数中使用命名空间
...mapActions('a', ['someAction'])

四、高级用法

1. 插件开发

const myPlugin = store => {
  // 初始化时调用
  store.subscribe((mutation, state) => {
    // 每次 mutation 之后调用
    console.log(mutation.type)
  })
}

const store = new Vuex.Store({
  // ...
  plugins: [myPlugin]
})

2. 严格模式

const store = new Vuex.Store({
  // ...
  strict: process.env.NODE_ENV !== 'production'
})

3. 表单处理

// 使用计算属性的 getter/setter
computed: {
  message: {
    get () {
      return this.$store.state.obj.message
    },
    set (value) {
      this.$store.commit('updateMessage', value)
    }
  }
}

五、最佳实践

  1. 项目结构组织

    store/
    ├── index.js          # 组装模块并导出 store
    ├── actions.js        # 根级别的 actions
    ├── mutations.js      # 根级别的 mutations
    ├── modules/
    │   ├── cart.js       # 购物车模块
    │   └── products.js   # 产品模块
    
  2. 遵循规则

    • 应用层级的状态应该集中到 store 中
    • 提交 mutation 是更改状态的唯一方法
    • 异步逻辑应该封装在 action 里面
  3. 模块化开发

    • 大型应用应该分割 store 为多个模块
    • 为业务相关的模块启用命名空间
  4. TypeScript 支持

    // store/types.ts
    export interface State {
      count: number
    }
    
    // store/index.ts
    import { InjectionKey } from 'vue'
    import { createStore, Store } from 'vuex'
    
    export const key: InjectionKey<Store<State>> = Symbol()
    
    export const store = createStore<State>({
      state: {
        count: 0
      }
    })
    

六、Vuex 与 Composition API

在 Vue 3 中使用 Vuex:

import { useStore } from 'vuex'

export default {
  setup() {
    const store = useStore()
    
    const count = computed(() => store.state.count)
    
    function increment() {
      store.commit('increment')
    }
    
    return {
      count,
      increment
    }
  }
}

七、Vuex 替代方案

  1. Pinia(Vue 3 推荐):

    • 更简单的 API
    • 更好的 TypeScript 支持
    • 组合式 API 友好
  2. Composition API 的 reactive

    • 小型应用可以使用 provide/inject + reactive
    • 适合简单状态管理需求

八、总结

Vuex 提供了集中式的状态管理方案:

  1. 核心流程

    • 组件 Dispatch → Actions → Commit → Mutations → Mutate State → Render
  2. 使用原则

    • 单一状态树
    • 状态响应式
    • 只能通过 mutation 修改状态
  3. 适用场景

    • 中大型单页应用
    • 多个组件共享状态
    • 需要跟踪状态变化
  4. 学习路径

    • 掌握基本概念(State, Getters, Mutations, Actions)
    • 理解模块化组织
    • 熟悉辅助函数使用
    • 了解插件开发和严格模式

对于新项目,特别是 Vue 3 项目,可以考虑使用 Pinia 作为更现代的替代方案,但理解 Vuex 的核心概念对于维护现有项目和学习状态管理原理仍然非常重要。