Vuex 状态管理
一种组件间通信的方式, 适用于任意组件间通信
概述
专门在Vue
中实现集中式状态、数据管理的一个Vue
插件, 对Vue
应用中多个组件的共享状态进行集中式的管理: 读、写
源码地址: https://github.com/vuejs/vuex
- 示例图:
Vuex 使用时机
- 多个组件依赖同一状态
- 来自不同组件的行为需要变更同一状态
Vuex 工作原理
Vuex
分为三部分:
Actions
: 用来处理异步回调获取数据的模块, 如调用后端API
, 如果没有异步操作可跳过Actions
直接调用Mutations
中的方法处理数据Mutations
: 用来处理State
中数据的模块State
: 用来存储数据的模块, 类型组件中的data
属性
- 示意图
环境搭建
第一步: 安装
- 安装
Vuex
:
npm i vuex
第二步: 应用Vuex
并创建store
需要在
Vue.use(Vuex)
应用Vuex
之后才能创建store
实例, 且模块化会将import
语句提前, 所有没有在main.js
中应用Vuex
在
src
目录新建store
文件夹, 并在文件夹中新建index.js
文件index.js
代码示例
// 引入 Vue
import Vue from 'vue'
// 引入 Vuex
import Vuex from 'vuex'
// 应用 Vuex
Vue.use(Vuex)
// 创建 actions => 响应组件中的动作
const actions = { ... }
// 创建 mutations => 操作 state 中的数据
const mutations = { ... }
// 创建 state => 存储数据
const state = { ... }
// 创建并导出 store
export default new Vuex.Store({
actions,
mutations,
state
})
第三步: 在main.js
中将store
挂载到Vue
中
- 代码示例
import store from './store'
new Vue({
el: '#app',
store
})
注意
应用Vuex
与创建store
实例的顺序问题, 不用在main.js
中应用Vuex
, 因为import
的store
会先执行
Vuex 基本使用
组件中读取Vuex
中的数据:
$store.state.value
组件中修改Vuex
中的数据:
$store.dispatch('actions中的方法名', 参数数据)
$store.commit('mutations中的方法名', 参数数据)
若没有网络请求或其他业务逻辑, 组件中可以越过actions
, 直接使用commit
调用mutations
中的方法
- 组件中示例代码:
export default {
data: {
n: 1
},
methods: {
add() {
this.$store.commit('addNormal', this.n)
},
addByWait() {
this.$store.dispatch('addWait', this.n)
}
}
}
store
中示例代码:
// 创建并导出 store
export default new Store({
actions: {
// 响应动作调用操作 mutations 中的事件
addWait() {
setTimeout(() => {
context.commit('addNormal', value)
}, 1000)
}
},
mutations: {
// 执行事件
addNormal(state, value) {
state.sum =+ value
}
},
state: {
sum: 0
}
})
Getters
概念: 用来加工state
中的数据, 相似于组件中的computed
计算属性, 当state
中的数据需要加工时使用
- 在
store
中配置getters
:
export default new Store({
getters: {
bigSum(state) {
return state.sum * 10
}
}
})
- 组件中读取数据
<template>
<h1> 当前求和X10为:{{ $store.getters.bigSum }} </h1>
</template>
Vuex 中 Map 方法的使用
注意
使用以下map
方法需要先在组件中引入: import { mapState, mapGetters, mapActions, mapMutations } from 'vuex'
mapState 方法
用于映射state
中的数据为计算属性, 共有两种写法:
- 对象写法:
{key: value}
形式,key
和value
一致或不一致时都可使用, 页面中使用key
获取数据 - 数组写法:
['xxx', 'yyy']
, 数组中的元素要与state
中的属性名一致, 页面中使用数组中元素获取数据
- 代码示例:
computed: {
// 对象写法
...mapState({getName: 'name', getAge: 'age'})
// 数组写法
...mapState(['name', 'age'])
}
mapGetters 方法
用于映射getters
中的数据为计算属性, 共有两种写法:
- 对象写法: 与上述
mapState
方法一致 - 数组写法: 与上述
mapState
方法一致
- 代码示例:
computed: {
// 对象写法
...mapGetters({newName: 'name', newAge: 'age'})
// 数组写法
...mapGetters(['name', 'age'])
}
mapActions 方法
用于生成与actions
对话的方法, 即包含$store.dispatch(xxx)
的函数, 共有两种写法:
- 对象写法:
{key: value}
形式,key
和value
一致或不一致时都可使用, 其中key
用于页面中的绑定事件处理函数 - 数组写法:
['xxx', 'yyy']
, 数组中的元素要与state
中的属性名一致, 数组中元素用于页面中的绑定事件处理函数
- 代码示例:
methods: {
// 对象写法
...mapActions({getName: 'getUserName', getAge: 'getUserAge'})
// 数组写法
...mapActions(['getName', 'getAge'])
}
注意
如需传参要在页面绑定事件时传递参数, 如<button @click="getName(xxx)">获取名字</button>
, 否则参数是默认的事件对象$event
mapMutations
用于生成与mutations
对话的方法, 即包含$store.commit(xxx)
的函数, 共有两种写法:
- 对象写法: 与上述
mapActions
方法一致 - 数组写法: 与上述
mapActions
方法一致
传参: 与上述mapActions
方法一致
- 代码示例:
methods: {
// 对象写法
...mapMutations({update: 'handleUpdate', del: 'handleDel'})
// 数组写法
...mapMutations(['update', 'del'])
}
Vuex 模块化
目的: 让代码更好维护, 让多种数据分类更加明确
模块化使用步骤
- 在
store
文件夹新建modules
文件夹 - 在
modules
文件夹中新建不同模块的.js
文件 - 在
.js
文件中分别配置actions
、mutations
和state
等并导出模块, 需要开启命名空间:namespaced: true
- 在
store/index.js
文件中分别引入模块, 并配置到modules
对象中
- 代码示例:
// store/modules/count.js 文件
export default {
namespaced: true,
actions: {
addWait(context, value) {
setTimeout(() => {
context.commit('ADD', value)
}, 1000)
}
},
mutations: {
ADD(state, value) {
state.sum += value
}
},
state: {
sum: 0
},
getters: {
bigSum(state) {
return state.sum * 10
}
}
}
// store/index.js 文件
import Vue from 'vue'
import Vuex from 'vuex'
import count from './modules/count.js'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
// count: count
count
}
})
使用不同模块中的方法
- 组件中获取模块
count
中state
的数据
computed: {
// 直接获取
sum() {
return this.$store.state.count.sum
}
// 使用 mapState 获取
...mapState('count', ['sum'])
}
- 组件中获取模块
count
中getters
的数据
computed: {
// 直接获取
bigSum() {
return this.$state.getters('count/bigSum')
}
// 使用 mapGetters 获取
...mapGetters('count', [' '])
}
- 组件中调用模块
count
中actions
的方法
methods: {
// 直接调用
handleAddWait() {
this.$store.dispatch('count/addWait')
}
// 使用 mapActions 调用
...mapActions('count', { handleAddWait: 'addWait' })
}
- 组件中调用模块
count
中mutations
的方法
methods: {
// 直接调用
handleAdd() {
this.$store.commit('count/ADD')
}
// 使用 mapMutations 调用
...mapMutations('count', { handleAdd: 'ADD' })
}