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>

效果
在这里插入图片描述
总结
这里获取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
}

加上这个之后就页面就报错了,因为加上这个属性之后他的actionsmutationsgetters都被限定在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的时候因为已经想好了怎么为了后续写博客,所以基本把这个四个函数怎么使用方式都写出来了,更具体的估计就要去看文档了。毕竟我理解的不如原作者的深刻。

写时一时爽,重构火葬场,我现在是深刻理解了这句话,不过这次项目的重构也让自己的技术体会更深了一点。不慌,慢慢来,加油

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值