1、引言
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。具体来说,Vuex将组件的共享状态抽取出来,以全局单例模式管理。在这种模式下,组件树构成了一个巨大的"视图",不管在树的哪个位置,任何组件都能获取状态或者触发行为。通过定义和隔离状态管理中的各种概念,并通过强制规则维持视图和状态间的独立性,代码将会变得更结构化且易维护。
Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试(允许开发者在开发过程中回溯和查看状态的变化历史,有助于快速定位问题并进行调试)、状态快照导入导出(开发者可以方便地导出当前应用的状态快照,以便日后分析或与他人共享。同时,也可以导入之前保存的状态快照,快速恢复到某一特定状态)等高级调试功能。
2、Vuex核心概念
- State:Vuex 中的单一状态树,以一个对象形式储存所有应用级的状态。
- Getters:从 State 中派生出来的状态,可以认为是 Store 的计算属性。
- Mutations:同步函数,用于更改 State 中的数据。每个 mutation 都有一个字符串的事件类型和一个回调函数。
- Actions:异步函数,用于处理异步操作和业务逻辑,然后提交 mutation。
- Modules:将 Store 分割成模块,每个模块拥有自己的 state、mutation、action、getter、甚至更深层次的嵌套模块。
javascript
// 安装 Vuex
npm install vuex --save
// 在 main.js 中引入 Vuex
import Vuex from 'vuex'
Vue.use(Vuex)
// 创建 Store
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++
}
},
actions: {
increment({ commit }) {
commit('increment')
}
},
getters: {
count: state => state.count
}
})
// 在 Vue 根实例中注册 store
new Vue({
el: '#app',
store,
// ...
})
// 组件中使用 Vuex
export default {
computed: {
count() {
return this.$store.getters.count
}
},
methods: {
increment() {
this.$store.dispatch('increment')
}
}
}
3、实践(以toC框架为例)
3.1 state
state是状态数据,可以通过this.$store.state来直接获取状态,也可以利用vuex提供的mapState辅助函数将state映射到计算属性(computed)中去。
javascript
export const state = () => ({
TagID:0,//当前tab的标记
companyID:"",//当前公司
page:1,//请求加载列表传给后台的页码,
loading:false,//list列表是否正在加载的状态标识
finished :false,//list列表数据是否全部加载完毕的标识
invoiceListAll:[],//当前页面展示的所有消息的集合
invoiceDataConfNum:["--","--","--"],//配置项tab页的开票消息数量
})
css
import { mapState } from 'vuex';
computed:{
...mapState(['invoiceDataConfNum'])
},
javascript
computed:{
// 使用计算属性表达
title( ){
return this.$store.state.title;
},
singer( ){
return this.$store.state.singer;
}
3.2 getters
有时候我们需要对 store 中的 state进行加工后再输出,
javascript
// 依赖并加工state中的数据,state中的数据也会相应改变
getters :{
invoiceDataConfNumOne(state){
return state.invoiceDataConfNum+'笔'
}
}
使用方式:this.$store.getters.invoiceDataConfNumOne
3.3 mutations
更改Vuex中的状态的唯一方法是提交 mutation
ini
export const mutations = {
updateCompanyID(state,companyID) {
state.companyID= companyID;
},
使用方式:
this.$store.commit("updateCompanyID",this.companyID);
3.4 actions
Action 提交的是 mutation,而不是直接变更状态,Action 可以包含任意异步操作。
ini
import {getSettleBillInvoiceList} from '../page-modules/inv/invoiceCenter/RequestInvoice';
export const actions = {
updateListData({commit,state}, that) {
getSettleBillInvoiceList(that).then(res=>{
let result = res.data;
commit("updateLoading",false)
let cdata = result.data.rows;
cdata = cdata.map((a)=>{
a.isChecked = false;
return a;
})
//非第一页数据要拼接数组
if(state.page==1&&cdata.length ==0){
commit("updateFinished",true);
}
cdata = state.invoiceListAll.concat(cdata) ;
commit("updateInvoiceListAll",cdata);
commit("updateInvoiceDataConfNum",[result.data.total1,result.data.total2,result.data.total3]);
}).catch(err=>{
console.log(err)
that.$TM.Toast.fail({ type: 'warning', message: "网络异常,获取数据失败" });
})
},
}
使用方式:this.$store.dispatch('updateListData',this)
3.5 modules
index.js为根模块,child1.js与child2.js两个子模块
store中的js写法如上所示,没有区别,只是取值调用时不同,如下:
- 取根模块中的值:this.$store.state.totalPrice
- 取子模块中的值:this.$store.state.child2.num
- 取子模块中的值:this.$store.state.child1.price
- 使用根模块的mutation中的方法:this.$store.commit('totalPrice')
- 使用子模块的mutation中的方法:this.$store.commit('child2/getNum',参数)
- 使用子模块的mutation中的方法:this.$store.commit('child1/getPrice',参数)