天天看點

vuex進階使用

接上文: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>

           

效果

vuex進階使用

總結

這裡擷取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;
},
           
vuex進階使用
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>

           

效果

vuex進階使用

命名空間: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的時候因為已經想好了怎麼為了後續寫部落格,是以基本把這個四個函數怎麼使用方式都寫出來了,更具體的估計就要去看文檔了。畢竟我了解的不如原作者的深刻。

寫時一時爽,重構火葬場,我現在是深刻了解了這句話,不過這次項目的重構也讓自己的技術體會更深了一點。不慌,慢慢來,加油