Vuex 模块化
为什么需要模块化?随着项目规模的增长,单一的store文件会变得庞大且难以管理;
Vuex 的模块化是一种组织和管理应用状态的策略:,它允许将全局的状态管理分解成更小、更可管理的部分;
逻辑清晰:将相关的状态、getter、mutation、action 分组,使得代码结构更加清晰;
命名空间:避免不同模块间命名冲突,通过模块化可以为每个模块,提供一个唯一的命名空间,方便管理;
性能与维护:模块化不仅提高了代码的可读性和可维护性,还能通过合理组织逻辑,间接提升应用的性能,
尤其是在大型应用中,通过懒加载和按需导入模块,可以进一步优化资源加载;
模块化实现步骤:
创建模块文件:在store目录下创建子目录,比如modules、在该目录下为每个模块创建单独的文件,如modulediy.js
/** 自定义Vuex模块: 声明并对外暴漏 state、mutations、actions、getters */conststate={userInfo:{name:'zs',age:18},}constmutations={}constactions={}constgetters={}exportdefault{state,mutations,actions,getters}src/store/index.js:文件中的modules配置项中,导入、注册这个模块;
// 导入 vue、vueximportVuefrom'vue'importVuexfrom'vuex'importmodulediyfrom'./modules/modulediy'//导入用户模块Vue.use(Vuex)//创建仓库 store 状态,即数据:conststore=newVuex.Store({//注册模块modules:{modulediy,}})// 导出仓库 storeexportdefaultstore在组件中使用模块化状态:创建Son4.vue组件—>组件内通过:$store.state.模块名.属性名查看获取Vuex模块化数据;
<template><divclass="box"><h2>Son4 子组件</h2>从vuex中获取的值:<label>{{ $store.state.count }}</label><hr/>从vuex modulediy 模块中获取的值:<label>{{ $store.state.modulediy.userInfo }}</label></div></template>获取模块 state数据
尽管已经分模块了,但其实子模块的状态,还是会挂到根级别的state中,属性名就是模块名,使用模块中的数据:
方式一:直接通过模块名访问:
$store.state.模块名.xxx方式二:通过
mapState映射,注意:Vuex模块中需要开启命名空间namespaced : true默认根级别的映射
mapState([ '内部属性名','内部属性名','模块名' ])指定子模块的映射 :
mapState('模块名', ['模块内对应属性名xx'])
<template><divclass="box"><h2>Son4 子组件</h2>从vuex中获取的值:<label>{{ $store.state.count }}</label><hr/>从vuex modulediy 模块中获取的值:<label>{{ $store.state.modulediy.userInfo }}</label><hr/>从vuex mapState中获取值:<label>{{ count }}</label><hr/>从vuex mapState中获取模块对象:<label>{{ modulediy }}</label><hr/>从vuex mapState 获取指定模块中获取的值:<label>{{ userInfo }}</label><hr/></div></template><script>import{mapState,mapGetters,mapMutations,mapActions}from'vuex';exportdefault{//计算属性:computed:{...mapState(['count','modulediy']),//获取内部属性、modulediy模块对象;...mapState('modulediy',['userInfo']),//还支持直接获取指定模块内、属性对象;}}</script>获取模块 gatters数据
modules/modulediy.js:gatters和state操作类似:对于启用了命名空间的模块,支持使用mapGetters辅助函数时;
conststate={userInfo:{name:'zss',age:18},str:"自定义模块state属性"}constgetters={getstr(state){return`年龄+1:${state.userInfo.age+1}`}}exportdefault{//开启命名空间namespaced:true,state,getters}组件获取模块gatters数据:
- 方式一:直接通过模块名访问
$store.getters['模块名/属性名'] - 方式二:通过
mapGetters映射,子模块的映射mapGetters('指定模块名', ['模块内属性名'])
注意:Vuex模块中需要开启命名空间namespaced : true
<template><divclass="box"><h2>Son4 子组件</h2>从vuex中获取的值:<label>{{ $store.state.count }}</label><hr/>从vuex modulediy 模块中获取的值:<label>{{ $store.state.modulediy.userInfo }}</label><hr/>从vuex mapState中获取值:<label>{{ count }}</label><hr/>从vuex mapState中获取模块对象:<label>{{ modulediy }}</label><hr/>从vuex mapState 获取指定模块中获取的值:<label>{{ userInfo }}</label><hr/>从vuex modulediy 模块getters中直接获取<label>{{ $store.getters['modulediy/getstr'] }}</label><hr/>从vuex modulediy 模块mapGetters中映射获取<label>{{ getstr }}</label><hr/></div></template><script>import{mapState,mapGetters,mapMutations,mapActions}from'vuex';exportdefault{//计算属性: mapState 和 mapGetters 都是映射属性computed:{...mapState(['count','modulediy']),//获取内部属性、modulediy模块对象;...mapState('modulediy',['userInfo']),//还支持直接获取指定模块内、属性对象; 需要开启命名空间;//mapGetters中映射获取 子模块的映射...mapGetters('modulediy',['getstr']),}}</script>获取模块 mutations数据
Vuex模块化操作:mutations,针对所在模块,对其state状态数据,进行修改的操作;
定义模块的 Mutations:和正常的Vuex中定义类似,如下:定义函数给模块内修改用户对象age值;
/** 自定义Vuex模块: 声明并对外暴漏 state、mutations、actions、getters */conststate={userInfo:{name:'zss',age:18},str:"自定义模块state属性"}constgetters={getstr(state){return`用户虚岁:${state.userInfo.age+1}`}}constmutations={//接收两个参数: state(必须 状态数据) payload(可选 传递参数)upgradeAgeM(state,payload){state.userInfo.age+=payload}}constactions={}exportdefault{namespaced:true,//开启命名空间state,getters,mutations,actions,}组件内使用:Vuex组件 Mutations:
方式一:原生方式直接通过
store调用:$store.commit('模块名/处理函数名', '传递参数')方式二:通过
mapMutations辅助函数映射子模块:mapMutations('模块名',['处理函数名'])
推荐的方式是使用mapMutations辅助函数,它可以帮助你将模块的mutations映射到组件的方法中,需要开启命名空间
<template><divclass="box"><h2>Son5 子组件</h2>从vuex中获取的值:<label>{{ $store.state.count }}</label><hr/>从vuex modulediy 模块中获取的值:<label>{{ $store.state.modulediy.userInfo }}</label><hr/>从vuex modulediy 模块getters中直接获取<label>{{ $store.getters['modulediy/getstr'] }}</label><hr/>直接调用:<button@click="upgradeAge(1)">给modulediy模块用户age+1</button><hr/>mapMutations调用:<button@click="upgradeAgeM(-1)">给modulediy模块用户age-1</button><hr/></div></template><script>import{mapState,mapGetters,mapMutations,mapActions}from'vuex';exportdefault{// mapMutations 和 mapActions 都是映射方法methods:{//原生方式调用Vuex组件: 给用户添加年龄;upgradeAge(n){this.$store.commit('modulediy/upgradeAgeM',n)},//mapMutations 子模块映射至methods 获取模块函数;...mapMutations('modulediy',['upgradeAgeM']),}}</script>获取模块 action数据
Vuex 组件action:只要是针对组件的,mutations进行异步操作扩展,本质和mutations 操作类似;
定义模块的 action:如下:内部调用mutations修改age函数,给其加上异步延迟的操作;
constactions={//actions处理异步: 不能直接操作state 还需要context.commit('mutation名','传参');upgradeAgeMSync(context,num){setTimeout(()=>{context.commit('upgradeAgeM',num)},1000)}}组件内使用:Vuex组件 action:
方式一:原生方式直接通过
store调用:$store.dispatch('模块名/处理函数名', '传递参数')方式二:通过
mapActions辅助函数映射子模块:mapActions('模块名',['处理函数名'])
<template><divclass="box"><h2>Son5 子组件</h2>从vuex中获取的值:<label>{{ $store.state.count }}</label><hr/>从vuex modulediy 模块中获取的值:<label>{{ $store.state.modulediy.userInfo }}</label><hr/>从vuex modulediy 模块getters中直接获取<label>{{ $store.getters['modulediy/getstr'] }}</label><hr/>直接调用:<button@click="upgradeAge(1)">给modulediy模块用户age+1</button><hr/>mapMutations调用:<button@click="upgradeAgeM(-1)">给modulediy模块用户age-1</button><hr/><br/>直接调用:<button@click="upgradeAgeSync(1)">延迟给modulediy模块用户age+1</button><hr/>mapActions调用:<button@click="upgradeAgeMSync(-1)">延迟给modulediy模块用户age+1</button><hr/></div></template><script>import{mapState,mapGetters,mapMutations,mapActions}from'vuex';exportdefault{// mapMutations 和 mapActions 都是映射方法methods:{//原生方式调用Vuex mutations组件: 给用户添加年龄;upgradeAge(n){this.$store.commit('modulediy/upgradeAgeM',n)},//mapMutations 子模块映射至methods 获取模块函数;...mapMutations('modulediy',['upgradeAgeM']),//原生方式调用Vuex actions组件: 延迟给用户添加年龄;upgradeAgeSync(n){this.$store.dispatch('modulediy/upgradeAgeMSync',n)},//mapActions 子模块映射至methods 获取模块函数;...mapActions('modulediy',['upgradeAgeMSync']),}}</script>Mutations 必须是同步的原因:
mutation保证了每次同步执行之后,应用状态都会立即发生变化:这使得时间旅行调试time-travel debugging成为可能;
DevTools 可以在每次 mutation 后捕获状态快照,从而支持状态的回溯和前进;
明确职责:mutations 专注于状态的直接变更,保持代码的纯净和单一职责原则;
状态一致性:确保状态改变的可预测性,每个 mutation 完成后都能对应到一个明确的新状态,便于理解和测试
Actions 支持异步的原因:
actions提供了一个封装异步操作和业务逻辑的地方:
可以触发多个mutations来分步骤改变状态,使得代码结构更清晰,易于维护,Actions是对 Mutations的异步扩展升级;
代码管理:
本代码已经使用Git进行管理: