接上文:vue-cli简单使用vuex
因为最近在对项目进行重构工作,所以就慢慢抽离了一些模块,最早做的就是重构了vuex模块,我发现我写的太垃圾了,我自己都看不下去了。所以在对vuex深入了解之后就动手把vuex模块无缝重构了,下面就是我在实验vuex的一些体会。
抽离层级
在上一篇文章中我们就发现我们的store文件就一个,这明显就不利于协助开发和维护,所以我们首先就是抽离store中各个模块的依赖。
目录
store
|__modules
|__module1.js
|__index.js
|__getters.js
|__mutations.js
|__actions.js
|__state.js
实际代码
state.js
export default {
count: 0
}
actions.js
export default{
title:state=>{
return 'StoreDemo'
}
}
mutations,js
export default {
increase(state) {
state.count++
},
subtract(state) {
state.count--
}
}
getters.js
export default{
title:state=>{
return 'StoreDemo'
}
}
index
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
// root级别的store
import state from './state'
import actions from './actions'
import mutations from './mutations'
import getters from './getters'
export default new Vuex.Store({
state,
getters,
actions,
mutations
})
storeDemo.vue
<template>
<div id="vuex">
{{title}}
<button @click="subtract">-</button>
{{count}}
<button @click="add">+</button>
</div>
</template>
<script>
export default {
data() {
return {
// count:store.state.count
};
},
computed: {
count() {
return this.$store.state.count;
},
//title
title(){
return this.$store.getters.title
}
},
methods: {
// 分发 Action
add() {
this.$store.dispatch("actionIncrease");
},
subtract() {
this.$store.dispatch("actionSubtract");
}
}
};
</script>
效果
总结
这里获取store使用了两种方式,一种是存储于state数据中,一种是通过getters方法获取,所以其实我们获取count也可以通过一个getters方法获取
getters.js
export default{
title:state=>{
return 'StoreDemo'
},
getCount:state=>{
return state.count
}
}
storeDemo.vue
count(){
return this.$store.getters.getCount;
//return this.$store.state.count;
},
Modules
实际项目中我们会把项目分为多个模块,所以为了配合开发,我们的store数据也应该分为各个对应的模块,所以我们前面的目录中模块就有作用了。
module1.js
const state = {
students: [{
name: '小明',
age: 16
}, {
name: '小红',
age: 18
}, {
name: '小夫',
age: 15
}, { name: '小陈', age: 16 }],
filterStudents: [],
title: 'Students'
}
const getters = {
//获取年龄最大的学生
maxAge(state) {
let student = state.students[0];
state.students.forEach(element => {
student = element.age > student.age ? element : student
});
return student.name
},
//获取筛选后的所有学生
getFilterStudents(state) {
return state.filterStudents
}
}
const actions = {
//获取未成年
getMinorStudents({ state, commit }) {
let students = state.students.filter(element => {
return element.age < 18;
})
students = students || []
console.log(students)
commit('getMinorStudents', students)
},
//获取成年人
getAdultStudents({ state, commit }) {
let students = state.students.filter(element => {
return element.age >= 18;
})
students = students || []
console.log(students)
commit('getAdultStudents', students)
},
}
const mutations = {
getMinorStudents(state, list) {
state.filterStudents = list;
},
getAdultStudents(state, list) {
state.filterStudents = list;
},
// 设置标题
setTitle(state, name) {
state.title = name
}
}
export default {
state,
getters,
actions,
mutations
}
index,js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
// root级别的store
import state from './state'
import actions from './actions'
import mutations from './mutations'
import getters from './getters'
// modules
import module1 from './modules/module1'
export default new Vuex.Store({
state,
getters,
actions,
mutations,
//模块
modules:{
module1
}
})
storeDemo.vue
<template>
<div id="vuex">
{{title}}
<button @click="subtract">-</button>
{{count}}
<button @click="add">+</button>
<p>{{moduleTitle}}</p>
<p>年龄最大的人:{{maxAge}}</p>
<button @click="getAdultStudents">获取成年人</button>
<button @click="getMinorStudents">获取未成年人</button>
<button @click="setTitle">修改标题</button>
<ul>
<p v-if="students.length==0">暂无数据</p>
<li v-for="(item,key) in students" :key="key">姓名:{{item.name}},年龄:{{item.age}}</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
// count:store.state.count
};
},
computed: {
// count() {
// return this.$store.state.count;
// },
count() {
return this.$store.getters.getCount;
},
title() {
return this.$store.getters.title;
},
//模块标题
moduleTitle() {
return this.$store.state.module1.title;//这里因为是module中的数据,要带上module名
},
//年龄最大的学生
maxAge() {
return this.$store.getters.maxAge;
},
//被筛选过后的数据
students() {
return this.$store.getters.getFilterStudents;
}
},
methods: {
// 分发 Action
add() {
this.$store.dispatch("actionIncrease");
},
subtract() {
this.$store.dispatch("actionSubtract");
},
// 获取未成年人
getMinorStudents() {
this.$store.dispatch("getMinorStudents");
},
//获取成年人
getAdultStudents() {
this.$store.dispatch("getAdultStudents");
},
//因为没有action事件,所以我们用commit方法分发事件
setTitle(){
this.$store.commit('setTitle','修改后的标题')
}
}
};
</script>
效果
命名空间:namespaced
这里用实际情况解释一下命名空间这个属性
module1.js
export default {
namespaced:true,
state,
getters,
actions,
mutations
}
加上这个之后就页面就报错了,因为加上这个属性之后他的actions
,mutations
,getters
都被限定在modules1
这个模块中了,所以后续操作这种方法就要改变了(vue文件中)
export default {
data() {
return {
// count:store.state.count
};
},
computed: {
// count() {
// return this.$store.state.count;
// },
count() {
return this.$store.getters.getCount;
},
title() {
return this.$store.getters.title;
},
//模块标题
moduleTitle() {
return this.$store.state.module1.title;
},
//年龄最大的学生
maxAge() {
return this.$store.getters['module1/maxAge'];
},
//被筛选过后的数据
students() {
return this.$store.getters['module1/getFilterStudents'];
}
},
methods: {
// 分发 Action
add() {
this.$store.dispatch("actionIncrease");
},
subtract() {
this.$store.dispatch("actionSubtract");
},
// 获取未成年人
getMinorStudents() {
this.$store.dispatch("module1/getMinorStudents");
},
//获取成年人
getAdultStudents() {
this.$store.dispatch("module1/getAdultStudents");
},
//因为没有action事件,所以我们用commit方法分发事件
setTitle(){
this.$store.commit('module1/setTitle','修改后的标题')
}
}
};
这个命名空间属性能够让我们更好的处理某个模块的store数据,而不用思考各个模块之间会造成的影响
模块引用
在实际项目中我们可能会有这样一种情况,这个模块的数据和别的模块数据有关联关系,碰到这种情况应该怎么办呢
getters.js
import module1 from './modules/module1'
//引用即可
export default{
title:state=>{
return module1.state.title
},
getCount:state=>{
return state.count
}
}
辅助函数
mapState
, mapGetters
, mapActions
,mapMutations
这几个函数我就不具体解释了,vuex官方文档解释的比较清楚了,我这里就直接全部改写后结合文档大家慢慢看
storeDemo.vue
<template>
<div id="vuex">
{{title}}
<button @click="subtract">-</button>
{{count}}
<button @click="add">+</button>
<p>{{moduleTitle}}</p>
<p>年龄最大的人:{{maxAge}}</p>
<button @click="getAdultStudents">获取成年人</button>
<button @click="getMinorStudents">获取未成年人</button>
<button @click="setTitle('修改后的标题')">修改标题</button>
<ul>
<p v-if="students.length==0">暂无数据</p>
<li v-for="(item,key) in students" :key="key">姓名:{{item.name}},年龄:{{item.age}}</li>
</ul>
</div>
</template>
<script>
import { mapState, mapActions, mapMutations, mapGetters } from "Vuex";
export default {
data() {
return {
// count:store.state.count
};
},
computed: {
...mapState({
count: state => state.count
}),
...mapGetters(["title"]),
...mapState("module1", {
moduleTitle: state => state.title
}),
...mapGetters("module1", ["maxAge"]),
...mapGetters("module1", {
students: "getFilterStudents"
})
},
methods: {
...mapActions({
add: "actionIncrease",
subtract: "actionSubtract"
}),
...mapActions("module1", ["getAdultStudents", "getMinorStudents"]),
...mapMutations("module1", ["setTitle"])
}
};
</script>
在做这个demo的时候因为已经想好了怎么为了后续写博客,所以基本把这个四个函数怎么使用方式都写出来了,更具体的估计就要去看文档了。毕竟我理解的不如原作者的深刻。
写时一时爽,重构火葬场,我现在是深刻理解了这句话,不过这次项目的重构也让自己的技术体会更深了一点。不慌,慢慢来,加油