接上文: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>
效果
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmL5YTM1UTO0kDMyIjNwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.gif)
總結
這裡擷取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的時候因為已經想好了怎麼為了後續寫部落格,是以基本把這個四個函數怎麼使用方式都寫出來了,更具體的估計就要去看文檔了。畢竟我了解的不如原作者的深刻。
寫時一時爽,重構火葬場,我現在是深刻了解了這句話,不過這次項目的重構也讓自己的技術體會更深了一點。不慌,慢慢來,加油