1、为什么要使用Vuex
- Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,它采用集中式存储管理应用的所有组件的状态。
- Vuex遵循“单向数据流” 理念,便于问题追踪以及提高代码可维护性。
- Vue中多个视图依赖于同一状态时,视图间传参和状态同步 较困难,Vuex能够很好解决该问题。
2、Vuex核心概念
- state: 保存数据状态,类似于vue的data选项
- getters: 从state派生出的新状态,类似于vue的computed选项
- mutations: 修改状态state
- actions:复杂业务逻辑, 类似于mutation,不同之处在于action提交的是mutation, 并且可以包含异步操作
- modules:模块化。将 store 分割成模块,每个模块拥有自己的 state、mutation、action、getter
这些核心概念的具体用法如下所示:
2.1、状态和状态变更:state和mutations
export default new Vuex.Store({
state: { count: 0 },
mutations: {
increment(state, n = 1) {
state.count += n;
}
}
})
<template>
<div>
<p>冲啊,扔了{{$store.state.count}}个炸弹</p>
<button @click="add">扔一个</button>
</div>
</template>
<script>
export default {
methods: {
add() {
this.$store.commit("increment");
}
}
};
</script>
2.2、派生状态:getters
export default new Vuex.Store({
getters: {
left(state) {
return 10 - state.count
}
}
})
<template>
<div>
<p>手榴弹还剩{{$store.getters.left}}</p>
</div>
</template>
2.3、动作:actions
export default new Vuex.Store({
actions: {
incrementAsync({commit}) {
setTimeout(() => {
commit('increment', 1)
}, 1000)
}
}
})
<template>
<div>
<button @click="addAsync">蓄力扔一个</button>
</div>
</template>
<script>
export default {
methods: {
addAsync() {
this.$store.dispatch("incrementAsync");
}
}
};
</script>
2.4、模块化:modules
将上面所有的示例按模块化的方式进行重构,完整代码如下所示:
// store/count.js
const count = {
// 命名空间
namespaced: true,
state: {
count: 0
},
getters: {
left(state) {
return 10 - state.count
}
},
mutations: {
increment(state) {
state.count += 1
}
},
actions: {
increment({ getters, commit }) {
// 复杂业务逻辑: 当炸弹有剩余时,才能继续扔炸弹
if (getters.left > 0) {
commit('add')
return true
}
return false
},
incrementAsync({ dispatch }) {
// 异步操作: 蓄力扔炸弹
return new Promise(resolve => {
setTimeout(() => {
resolve(dispatch('add'))
}, 1000)
})
}
},
}
export default count
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import count from './count'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
// 把count命名为bomb
bomb: count
}
})
<!--TestVuex.vue-->
<template>
<div>
<p>炸弹扔了{{$store.state.bomb.count}}个</p>
<p>炸弹还剩{{$store.getters['bomb/left']}}个</p>
<button @click="Throw">扔一个炸弹</button>
<button @click="asyncThrow">蓄力扔一个炸弹</button>
</div>
</template>
<script>
export default {
methods: {
async Throw() {
const result = await this.$store.dispatch("bomb/add");
if (!result) {
alert("没炸弹了");
}
},
async asyncThrow() {
const result = await this.$store.dispatch("bomb/asyncAdd");
if (!result) {
alert("没炸弹了");
}
}
}
};
</script>