Vuex 3使用总结

本文详细介绍了Vuex 3的状态管理模式,包括安装使用、简单示例及五大核心概念:State、Getters、Mutations、Actions和Modules。Vuex解决了Vue项目中多组件共享状态的管理问题,提供了集中式的存储方案。文中还给出了具体的代码示例,帮助读者理解和应用Vuex。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

版本问题

截止博客发布前,Vuex 拥有 3.x 和 4.x 版本。

本文总结的是与 Vue 2 匹配的 Vuex 3 的使用。

更多操作请参考官方文档:https://v3.vuex.vuejs.org/

与 Vue 3 匹配的 Vuex 4 的文档: https://vuex.vuejs.org/

状态管理模式

写过 vue 项目的程序员应该都知道父子组件传参的方式,通过子组件的 props 参数,和 $emit 来触发事件。

但是当遇到多个组件共享状态时,传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力,甚至会导致无法维护的代码。

基于此,把组件的共享状态抽取出来,以一个全局单例模式管理,vuex 就产生了。

在这里插入图片描述

安装使用

Vue 2 的脚手架项目,安装 3.6.2版本。

npm install vuex@3.6.2 --save

在 src 目录下新建 store 文件夹,在该目录下新建 index.js

index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const state = {
  count: 1
}

const getters = {

}

const mutations = {
  add(state, n) {
    state.count += n
  },
  reduce(state) {
    state.count--
  }
}

const actions = {

}

export default new Vuex.Store({
  state,
  getters,
  mutations,
  actions
})

入口文件引入

main.js

import store from './store'

new Vue({
  el: '#app',
  store,
  components: {
    App
  },
  template: '<App/>'
})

简单示例

通过 commit 提交 mutation 中的方法修改 state。

组件代码

<template>
  <div>
    <el-button @click="$store.commit('add', 1)">add</el-button>
    <el-button @click="$store.commit('reduce')">reduce</el-button>

    <div>值:{{ $store.state.count }}</div>
  </div>
</template>

在实际开发过程中,直接使用 $store. 这样的方式似乎不太优雅,可以参考以下写法。

<script>
import { mapState, mapMutations } from "vuex";

export default {
  name: "vuex",
  data() {
    return {};
  },
  computed: {
    ...mapState(["count"])
  },
  mounted() {
  },
  methods: {
    ...mapMutations(["add", "reduce"])
  }
};
</script>

方法调用

<template>
  <div>
    <el-button @click="add(1)">add</el-button>
    <el-button @click="reduce">reduce</el-button>

    <div>值:{{ count }}</div>
  </div>
</template>

五大核心概念

1、State

相当于 Vue 中的 data,以及 React 中的 state。

Vuex 使用单一状态树,用一个对象就包含了全部的应用层级状态,单状态树和模块化并不冲突。

获取 state

如上述示例所示,html 中可以使用 $store.state.count 获取(属性访问),js 中需要在前面加 this.

还可以通过 mapState 辅助函数,将状态加入计算属性中。

2、Getters

getter可以认为是 store 的计算属性,返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

如果有多个组件需要共用状态的某计算属性,可以使用它。

修改上述 index.js

const state = {
  count: 1,
  todos: [{
      id: 1,
      text: '...',
      done: true
    },
    {
      id: 2,
      text: '...',
      done: false
    }
  ]
}

const getters = {
  doneTodos: state => {
    return state.todos.filter(todo => todo.done)
  }
}

mapGetters 辅助函数

import { mapGetters, mapMutations } from "vuex";

computed: {
    ...mapGetters(["doneTodos"])
  },
  mounted() {
    console.log(this.doneTodos); // 
  },

3、Mutations

更改状态的唯一方法是提交 mutation。

如上示例,mutation 中可以定义更改状态 state 的方法。也可以使用常量替代 Mutation 事件类型。

// mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION'
const mutations = {
  // 我们可以使用一个常量作为函数名
    [SOME_MUTATION] (state) {
      // mutate state
    }
}

注意:一条重要的原则就是要记住 mutation 必须是同步函数。

在组件中提交 mutation 主要用到 commit 方法,或者 mapMutations 辅助函数,参考上述示例。

4、Actions

Action 类似于 mutation,不同在于:

Action 提交的是 mutation,而不是直接变更状态。
Action 可以包含任意异步操作。

也就是说,如果有需要进行后台接口更新操作,需要使用 Action。

修改上述 index.js

const actions = {
  addAsync({ commit }) {
    setTimeout(() => {
      commit('add', 10)
    }, 1000);
  }
}

在组件中使用 this.$store.dispatch('xxx') 分发 action,或者使用 mapActions 辅助函数,调用类似 mapMutations

5、Modules

module,即模块。Vuex 允许多模块以应对复杂的应用而造成 store 对象臃肿的问题。

为了方便管理,在 store 下新建 modules 目录,然后在该目录下新建一个 dept.js。

dept.js

const state = {
  deptList: [{
    deptID: 0,
    deptName: '总经理室'
  }]
}

const getters = {}

const mutations = {
  add(state, dept) {
    state.deptList.push(dept)
  }
}

const actions = {}

export default {
  namespaced: true, // 使用命名空间
  state,
  actions,
  getters,
  mutations
}

然后修改 store 目录下的 index.js,引入模块

const modules = {}
const require_module = require.context('./modules', false, /.js$/)
require_module.keys().forEach(file_name => {
  console.log(file_name)
  modules[file_name.slice(2, -3)] = require_module(file_name).default
})

export default new Vuex.Store({
  modules,
  state,
  getters,
  mutations,
  actions
})

组件调用 state

<div>{{ $store.state.dept.deptList }}</div>

// 或
<div>{{ dept.deptList }}</div>

computed: {
    ...mapState(["dept"])
  },

调用 mutation

this.$store.commit("dept/add", { deptName: "开发部", deptID: 1 });

// 或
<el-button @click="add({deptName: '开发部'})">add</el-button>
methods: {
    ...mapMutations("dept", ["add"])
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值