使用Vuex
在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信。
1. Vuex使用场景
- 多个组件依赖于同一状态
- 来自不同组件的行为需要变更同一状态 相对于全局总线,Vuex更适合不止2个组件的数据通信繁琐配置。
2. Vuex的工作原理
Actions并不多余,可以用来支持后代请求、校验等需求
3. 使用Vuex
3.1 安装Vuex
// 安装vuex
npm i vuex@3
3.2 js文件配置
创建store文件夹,在store下面创建index.js文件
// 该文件用于创建Vuex中最为核心的store
import Vuex from "vuex"
// 准备actions-- 用于响应组件中的动作
const actions = {}
// 准备mutations---用于操作数据(state)
const mutations = {}
// 准备state--用于存储数据
const state = {}
// 创建store
const store = new Vuex.Store({
actions,
mutations,
state
})
// 暴露store,可以简写直接export上面store
export default store
// 引入vue
import Vue from 'vue'
import Vuex from "vuex"
// 引入App组件,它是所有组件的父组件
import App from './App.vue'
// 关闭vue的生产提示
Vue.config.productionTip = false
// 可以不写index.js, 注意使用简写如果没有index.js就会报错
import store from "@/store";
Vue.use(Vuex)
// 创建vm实例对象
new Vue({
// 将App组件放到容器中
render: q => q(App),
store,
beforeCreate() {
Vue.prototype.$bus = this
}
}).$mount('#app')
运行发现报错: 按照报错提示需要先Vue.use(Vuex)再创建store实例对象,如果简单的调换第10行和12行代码,问题依旧,原因在于es6中import的执行优先其他代码执行,也就是执行的时候会扫描import语句,将所有import语句汇总到一起优先执行,在执行后面的其他语句。
解决办法:将Vue.use(Vuex)移动到index.js中去。
// 该文件用于创建Vuex中最为核心的store
import Vuex from "vuex"
// 准备actions-- 用于响应组件中的动作
const actions = {}
// 准备mutations---用于操作数据(state)
const mutations = {}
// 准备state--用于存储数据
const state = {}
Vue.use(Vuex)
// 创建store
export default new Vuex.Store({
actions,
mutations,
state
})
页面不再报错,vm实例出现$store属性信息:
编写index.js中actions, mutations
// 该文件用于创建Vuex中最为核心的store
import Vue from 'vue'
import Vuex from "vuex"
// 准备actions-- 用于响应组件中的动作
const actions = {
// 没有处理逻辑,可以直接commit
/* 'jia': function (context, num){
context.commit('JIA', num)
},
'jian': function (context, num){
context.commit('JIAN', num)
},*/
jiaSumOdd(context, num) {
if (context.state.sum % 2 == 1) {
context.commit('JIA_SUM_ODD', num)
}
}
}
// 准备mutations---用于操作数据(state)
const mutations = {
'JIA': function (state, num){
state.sum += num
},
'JIAN': function (state, num){
state.sum -= num
},
JIA_SUM_ODD(state, num) {
state.sum += num
}
}
// 准备state--用于存储数据
const state = {
sum: 0
}
Vue.use(Vuex)
// 创建store
export default new Vuex.Store({
actions,
mutations,
state
})
打开开发者工具:
- 不建议把所有逻辑代码都写到actions里面,因为开发者工具监测不到, 也不建议逻辑代码都写到组件里面,使用commit到mutations, 如果逻辑非常复杂代码很多,这样组件不能代码复用
- 组件中读取vuex中的数据: $store.state.sum
- 组件中修改vuex中的数据: $store.dispatch('actions中的方法名',数据)或者$store.commit('mutations中的方法名', 数据)
提示
若没有网络请求或者其他业务逻辑,组件中可以越过actionss,即不写dispatch, 直接编写commit
4. getters配置
如果涉及到vuex中的数据需要计算才能展示数据:
- 可以直接在组件中使用插值语法
- 可以在组件中使用计算属性
- 可以使用getters配置
- 概念: 当state中的数据需要经过加工后再使用时, 可以使用getters加工。
- 在store.js中追加getters配置
const getters = {
bigSum(state){
return state.sum * 10
}
}
Vue.use(Vuex)
// 创建store
export default new Vuex.Store({
......
getters
})
- 组件中读取数据:
$store.getters.bigSum
5. 使用mapState和mapGetters简化读取Vuex数据
如果不使用mapState和mapGetters, 那可以使用computed属性, 不过编码需要写不少代码 mapState方法:用于帮助我们映射state中的数据为计算属性 mapGetters方法:用于帮助我们映射getters中的数据为计算属性
5.1 引入mapState,mapGetters函数
import {mapState, mapGetters} from "vuex";
5.2 查看使用mapState帮我们生成的函数
mounted() {
const x = mapState({he: 'sum'})
console.log(x)
}
可以看到生成一个名字叫mappedState的函数, 名字不需要关心也用不到,它对应的属性是he,我们用he即可调用到mappedState函数 将mapState帮我们生成的函数加到computed中
computed:{
// 借助mapState生成计算属性,从state中读取数据。(对象写法)
// ...mapState({he: 'sum'})
// 数组写法
...mapState(['sum']),
// 借助mapGetters生成计算属性,从getters中读取数据。(数组写法)
...mapGetters(["bigSum"])
},
5.3 mapActions和mapMutations
使用mapActions和mapMutations方法简化dispatch和commit mapActions方法: 用于帮助我们生成与actions对话的方法, 即包含$store.dispatch(xxx)的函数 mapMutations方法: 用于帮助我们生成与mutations对话的方法,即:包含$store.commit(xxx)函数