Vuex 使用详解

小编 2026-06-27 阅读:627 评论:0
阅读数:187说明Vuex 是一个专门为 Vue 应用程序开发的状态管理模式,适合开发大型单页应...

阅读数:187

说明

Vuex 是一个专门为 Vue 应用程序开发的状态管理模式,适合开发大型单页应用, 它能够更好的在组件外部管理状态

重要文件版本

  • “vue”: “^2.5.2”,
  • “vuex”: “^3.0.0”

特点

每一个 Vuex 应用的和兴就是 store(仓库)。store 基本上就是一个容器,它包含着应用中大部分的状态(state) Vuex 和单纯的全局对象有以下不同

  1. Vuex的状态储存是响应式的,当 Vue 组件从 store 中读取状态时,若store中的状态发生变化,那么相应的组件也会得到高效更新
  2. 不能直接改变 store 中的状态,改变 store 中状态的唯一途径就是显式的提交(commit)mutation 这样可以更方便的跟踪状态的变化

1. 安装及引入

1. 下载

 npm install --save vuex
  • 1
  • 1

2. 安装

 // 配置 store  import Vue from 'vue'; import Vuex from 'vuex'; // 通过 Vue.use() 安装 Vuex Vue.use(Vuex); const store = new Vuex.Store({ state: {}, }); export default store; // main.js 中引入 store import store from './store/index'; new Vue({ el: '#app', store, // 将 store 实例从根组件中‘注入’到每一个子组件中,子组件通过 `this.$store` 调用 template: '<app/>', components: { App } });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

2. API 详解

一个完整的 store 配置

 const store = new Vuex.Store({ state: {}, getters: {},  mutations: {},  actions: {}, modules: { home: { state: {}, getters: {},  mutations: {},  actions: {}, } }, strict: process.env.NODE_ENV !== 'production' });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

1. state

Vuex 中使用单一状态树,包含了全部应用层级状态,每个应用将仅仅包含一个 store 实例

在 Vue 组件中获得 Vuex 状态

 // 根组件中注入 import store from './store.js'; const vm = new Vue({ el: '#app', store, // store 实例注入 }) // Vue 组件中使用 const Child = { template: `<div>this is {{count}}</div>`, computed: { count() { return this.$store.state.count; } } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

2. mapState 辅助函数

为了解决 组件在获取多个状态的时候,频繁声明为计算属性有些重复和冗余,可以使用 mapState 辅助函数帮助生成计算属性

 import { mapState } from 'vuex'; import HomeBasic from '../components/Home/HomeBasic'; export default { name: 'Home', data () { return {}; }, components: { HomeBasic }, computed: { step() { // 普通计算属性 return 3; }, ...mapState({ // 从 state 中的到的计算属性 count: state => state.global,// 可以是一个函数 count: 'global', // 可以是一个字符串,等同于 ‘state => state.global’ count(state) { // 可以计算 return state.global - this.step; } }) }, };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

3. getter

state 中一般存放的都是比较原始的数据,我们的应用中使用的可能会是这些原始的数据经过计算后的数据,这时候我们可以在 组件的计算属性中操作

 computed: { ...mapState({ count(state) { return state.global * 100; } }) },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

如果有多个组件都需要使用这种计算后的属性,这个时候可以使用 getter ,一种类似 Vue 组件中计算属性的方式,同样 getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

 // 定义 getter const store = new Vuex.Store({ state: { global: 100, step: 3 }, getters: { count(state) { // 第一个参数是 state  return state.global * 200; }, changeCount(state, getters) { // 可以传入两个参数 第二个参数是当前的 getter  return getters.count - state.step; }, addCount: (state, getters) => (num) => { // 值可以是一个函数,用于传递参数 return getters.count - state.step + num; } },  }); // 组件中使用 computed: { count() { return this.$store.getters.count; }, count2() { return this.$store.getters.changeCount; }, count3() { return this.$store.getters.addCount(10); // 传参 }, ...mapState({ }) },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

4. mapGetters 辅助函数

与 mapState() 类似 mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性

 computed: { ...mapGetters([ // 参数为数组时,可以将同名的属性映射 'count'  ]), ...mapGetters({ // 参数为对象时可以设置映射的名称 count2: 'changeCount' }) },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

5. mutation

以上 state、getter 都是用来获取 store 中状态的,而更改 store 中状态只能通过提交 mutation ,每个 mutation 都由一个事件类型(type)和一个事件处理函数(handler),事件处理函数接受 state 作为参数,只有在这里才可以进行状态更改

提交 mutation 需要用到 store 的 store.commit() 方法

注意: mutation 函数必须是同步的

 // 创建 mutation const ADD_COUNT = 'ADD_COUNT'; // 用常量代替事件类型,使得代码更清晰 const store = new Vuex.Store({ state: { global: 100, step: 3 }, mutations: { [ADD_COUNT] (state, num) { // 第一个参数为 state 用于变更状态 state.global += num; }, [ADD_COUNT] (state, payload) { // 第二个参数为提交的参数,参数类型视提交方式而定 state.global += payload.num; }, } }); // 组件中提交 methods: { handleClick() { this.$store.commit('ADD_COUNT', 30); // 普通提交 第二个参数为参数 this.$store.commit('ADD_COUNT', { num: 30 }); // 可以将参数包装到一个对象中提交 this.$store.commit({ // 可以直接提交一个对象,对象中 type 属性对应 事件类型,其他属性, 成为事件处理函数的第二个参数对象中的属性 type: 'ADD_COUNT',  num: 30 }); }, },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

6. mapMutations 辅助函数

同 mapState 和 mapGetters 一样,mapMutations 可以节约代码,使代码更加简洁,他将会在组件的 methods 属性中完成映射

 methods: { handleClick() { this.addCount({ num: 40 }); this.ADD_COUNT({ num: 60 }); }, ...mapMutations({  addCount: 'ADD_COUNT' // 将 this.addCount({}) 映射为 this.$store.commit('ADD_COUNT', {}) }), ...mapMutations([ // 参数为数组表示函数名不变 'ADD_COUNT' ]) },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

7. action

action 类似于 mutation, 不同在于:

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

Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。

// 创建 actions  const store = new Vuex.Store({ state: { global: 100, step: 3 }, mutations: { [ADD_COUNT] (state, payload) {  state.global += payload.num; }, }, actions: { changeCount(context, payload) { // 第一个参数为 store 实例类似的对象 context.commit({ type: ADD_COUNT, ...payload }); }, changeCount({ commit }, payload) { // 一般使用解构赋值 commit({ type: ADD_COUNT, num: payload.num }); }, changeCount({ commit }) { // action 中可以尽心异步操作,并且可以提交多次 mutation  request('/api').then(res => { commit({ type: ADD_COUNT, num: res.data.num }); }).catch(() => { commit({ type: ERROR }); }); } } }); // Vue 组件中使用 methods: { handleClick() { this.$store.dispatch('changeCount', { num: 1 }); this.$store.dispatch({ // 注意如果使用这种方式,changeCount 接受的 payload 中是包含 type: 'changeCount' 字段的 commit 的时候要去除 type: 'changeCount', num: 30 }); }, },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

8. mapActions 辅助函数

与 mapMutations 类似,用于将 actions 映射到组件中

 methods: { handleClick() { this.changeCount({ num: 3 }); }, ...mapActions({ changeCount: 'changeCount' }) ...mapActions([ 'changeCount' ]) },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

actions 可以组合使用,也就是在一个 action 中调用另外一个 action

9. module

解决使用单一状态树,所有状态集中,使得对象过大的问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割,以下是官网的例子

 const moduleA = { state: { ... }, mutations: { ... }, actions: { ... }, getters: { ... } } const moduleB = { state: { ... }, mutations: { ... }, actions: { ... } } const store = new Vuex.Store({ modules: { a: moduleA, b: moduleB } }) store.state.a // -> moduleA 的状态 store.state.b // -> moduleB 的状态
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

模块的局部状态

  • 对于模块内部的 mutation 和 getter,接收的第一个参数是模块的局部状态对象。
  • 对于模块内部的 action,局部状态通过 context.state 暴露出来,根节点状态则为 context.rootState
  • 对于模块内部的 getter,根节点状态会作为第三个参数暴露出来

10. 模块化使用方式

在辅助函数中使用 module 中数据
 export default { computed: { ...mapState({ // 要使用 模块中的 state 需要 通过 state.[模块名].[模块数据] 引用 moduleAData: state => state.moduleA.moduleAData }), ...mapGetters({ // 要使用 模块中的 getter 根使用全局的 getter 一致,因为模块内的 getter 是注册在全局命名空间的 moduleAGetterData: 'moduleAGetterData' }) }, methods: { // mutation、action 与 getter 一样,模块内的 mutation、action 也是注册在全局命名空间的 ...mapMutations({ changeTestList: 'changeTestList' }), ...mapActions([ changeTestList: 'changeTestList' ]) }, components: { SideBarMenu, BasicHeader } };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
给模块添加命名空间,以提高封装性

模块中添加 namespaced: true 可以使其成为命名空间模块,模块被注册后,模块内所有 getter action mutation 都会 自动根据 模块注册路径调整命名 (如下)

 // 定义模块 const moduleA = { namespaced: true, // 添加命名空间 state: { test: 'abc' }, getters: { upperTest(state) { return state.test.toUpperCase();  } }, mutations: { changeTest(state, paylaod) { state.test = payload.test; } } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

组件中使用

 export default { computed: { ...mapState({ test: state => state.moduleA.test // 模块中的 state 本来就是有层级的所以这里不变 }) ...mapGetters({ upperTest: 'moduleA/upperTest' // 这里的引用要加上模块名 }) }, methods: { ...mapMutations({ changeTest: 'moduleA/changeTest' // action 与 mutation 与 getter 的使用一致 }) }, }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

组件中使用的简易写法 给 mapState mapGetters mapMutations mapActions 的第一个参数传入模块的空间名称,这样所有绑定都会自动将该模块作为上下文。

 export default { computed: { ...mapState('moduleA', ['test']) //传入第一个参数表示绑定的上下文 ...mapGetters('moduleA', { upperTest: 'upperTest'  }) }, methods: { ...mapMutations('moduleA', { changeTest: 'changeTest'  }) }, }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

11. 严格模式

在严格模式下,无论何时发生了状态变更且不是由 mutation 函数引起的,将会抛出错误。这能保证所有的状态变更都能被调试工具跟踪到。

 const store = new Vuex.Store({ strict: process.env.NODE_ENV !== 'production' })
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

对比 redux

  • Vuex 与 Redux 都使用了单一组件树,状态都存放在 state 中
  • 如果某个状态的使用涉及到固定的计算处理,那么 Vuex 中可以通过设置 getter 来提取出公共的状态变化方法,而 Redux 中只能在各个组件中处理或者提取出一个函数
  • Vuex 中状态更改只能通过提交(commit)mutation ,而且不能是异步的, Redux 中 reducer 也包括这部分功能;reducer 会接收含有事件类型的对象(type属性)然后根据 type 的类型返回新的 state ,Vuex 中的 mutation 会根据不同的事件类型,对传入的 state 进行操作。
  • Vuex 中如果有异步操作需要更改状态的,要使用 action,action 用来在异步操作后 通过 commit 提交 mutations; 在 Redux 中 action 的功能与其一致,提交更改用的是 dispatch 方法(Vuex 中也有 dispatch 方法,但是是用来触发 action 的)。
  • Vuex 中分割模块用的是 module 属性,这个需求在 Redux 中是通过 创建 reducer 是,分模块引入不同的 初始 state 完成的。
  • Vuex 中为了方便在组件中使用 状态或者状态变更函数,引入了 一些辅助函数 mapState、mapGetters、mapMutations、mapActions;Redux 为配合 React 需要引入 React-Redux 的 connect 方法,将状态与状态处理函数注入到组件中,实现了同样功能

相关文章




 <div class="article-bar-bottom"> <div class="article-copyright"> 版权声明:转载请注明原文地址 https://blog.csdn.net/mjzhang1993/article/details/78321903 </div> <div class="tags-box artic-tag-box"> <span class="label">文章标签:</span> <a class="tag-link" href="http://so.csdn.net/so/search/s.do?q=vue&amp;t=blog" target="_blank">vue </a><a class="tag-link" href="http://so.csdn.net/so/search/s.do?q=vuex&amp;t=blog" target="_blank">vuex </a><a class="tag-link" href="http://so.csdn.net/so/search/s.do?q=api&amp;t=blog" target="_blank">api </a><a class="tag-link" href="http://so.csdn.net/so/search/s.do?q=module&amp;t=blog" target="_blank">module </a><a class="tag-link" href="http://so.csdn.net/so/search/s.do?q=computed&amp;t=blog" target="_blank">computed </a> </div> <div class="tags-box"> <span class="label">个人分类:</span> <a class="tag-link" href="https://blog.csdn.net/mjzhang1993/article/category/7220387" target="_blank">vue全家桶 </a> </div> </div><!-- !empty($pre_next_article[0]) --> </div>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

原文发布时间:06月30日

原文作者:qyl_0316

本文来源CSDN博客如需转载请紧急联系作者

版权声明

本文仅代表作者观点,不代表百度立场。
本文系作者授权百度百家发表,未经许可,不得转载。

热门文章
  • 机房智能化温湿度解决方式之POE供电以太网温湿度传感器

    机房智能化温湿度解决方式之POE供电以太网温湿度传感器
    机房智能化温湿度解决方式之POE供电以太网温湿度传感器 北京盈创力和电子科技有限公司 智能型TCP网口温湿度记录仪 北京IP网络温湿度记录仪厂家,北京盈创力和 北京智能型TCP网口温湿度记录仪IP网络温湿度记录仪是一种新型的基于TCP/IP协议双绞线以太网标准温湿度采集模块,利用它可以实现现场温度值、相对湿度值的采集,同时利用其自身的RJ45通信接口可以方便地和机房监控主机或交换机集线器进行联网。 工作于-40℃~85℃工业级带...
  • Sequential Monte Carlo Methods (SMC) 序列蒙特卡洛/粒子滤波/Bootstrap Filtering

    Sequential Monte Carlo Methods (SMC) 序列蒙特卡洛/粒子滤波/Bootstrap Filtering
    Problem Statement 我们考虑一个具有马尔可夫性质、非线性、非高斯的状态空间模型(State Space Model):对于一个时间序列上的观测结果{yt,t∈N}\\{ y_t , t \\in N \\}{yt​,t∈N},我们认为每个观测结果yty_tyt​的生成依赖于一个无法直接观察的隐变量xt∈{xt,t∈N}x_t \\in \\{x_t , t \\in N \\}xt​∈{xt​,t∈N},即:p(...
  • HTTP状态保持的原理

    HTTP状态保持的原理
    a)在用户登录之后,浏览器返回响应的时候会在响应中添加上cookieb)浏览器接收到cookie之后会自动保存c)当用户再次请求同一服务器中的其他网页的时候,浏览器会自动带上之前保存的cookied)服务接收到请求之后可以请 request 对象中取到cookie 判断当前用户是否登录  Http是无状态的,就是连接时数据互通,关闭后...
  • Hive 系统函数及示例

    Hive 系统函数及示例
    查看所有系统函数 show functions; 函数分类 内置函数【系统函数】 数学函数: floor、round、ceil、cos、log2等 字符串函数: length、reverse、trim、lower、get_json_object、repeat等 收集函数: size 转换函数: cast 日期函数: year、month、datediff、date、date_add等 条件函数: coalesce、case…w...
  • CSRF的原理和防范措施

    CSRF的原理和防范措施
    a)攻击原理:i.用户C访问正常网站A时进行登录,浏览器保存A的cookieii.用户C再访问攻击网站B,网站B上有某个隐藏的链接或者图片标签会自动请求网站A的URL地址,例如表单提交,传指定的参数iii.而攻击网站B在访问网站A的时候,浏览器会自动带上网站A的cookieiv.所以网站A在接收到请求之后可判断当前用户是登录状态,所以...
标签列表