VUE学习(二十一)、Vuex(getters、mapState与mapGetters、mapMutations与mapActions、多组件共享数据、模块化编码)

VUE学习(二十一)、Vuex(getters、mapState与mapGetters、mapMutations与mapActions、多组件共享数据、模块化编码)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jjv2YBIr-1644474963310)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20220209141221565.png)]

一、Vuex普通实现求和案例

演示

在这里插入图片描述

实现

1、引入Vuex(store文件下index.js)

//该文件用于创建Vuex中最为核心的store
import Vue from "vue";
/* 
	此处不写在App.vue中的原因
	是因为应该先Vue.use(Vuex)再创建store实列对象
	但是es6规定import语句先执行,如果写在App.vue中
	则会出现先创建store实列对象再Vue.use(Vuex)的情况
*/
//引入Vuex
import Vuex from "vuex";
//应用Vuex插件
Vue.use(Vuex);
/*  
    操作数据前需要进行业务逻辑处理则写在actions中,如果仅仅直接修改数据
    就没必要写在actions中,直接调用mutations就行
*/
//准备actions——用于响应组件中的动作
const actions = {
    /* jia(context,value){
		console.log('actions中的jia被调用了')
		context.commit('JIA',value)
	},
	jian(context,value){
		console.log('actions中的jian被调用了')
		context.commit('JIAN',value)
	}, */
    jiaOdd(context, value) {
        console.log("actions中的jiaOdd被调用了");
        if (context.state.sum % 2) {
            context.commit("JIA", value);
        }
    },
    jiaWait(context, value) {
        console.log("actions中的jiaWait被调用了");
        setTimeout(() => {
            context.commit("JIA", value);
        }, 500);
    }
};
/*  
    mutations注重于操作数据,如果操作数据前有一定的业务逻辑则写在actions中
*/
//准备mutations——用于操作数据(state)
const mutations = {
    JIA(state, value) {
        console.log("mutations中的JIA被调用了");
        state.sum += value;
    },
    JIAN(state, value) {
        console.log("mutations中的JIAN被调用了");
        state.sum -= value;
    }
};
//准备state——用于存储数据
const state = {
    sum: 0 //当前的和
};

//创建并暴露store
export default new Vuex.Store({
    actions,
    mutations,
    state
});

2、Count.vue组件

<template>
    <div>
        <h1>当前求和为:{{ $store.state.sum }}</h1>
        <select v-model.number="n">
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>
        </select>
        <button @click="increment">+</button>
        <button @click="decrement">-</button>
        <button @click="incrementOdd">当前求和为奇数再加</button>
        <button @click="incrementWait">等一等再加</button>
    </div>
</template>

<script>
export default {
    name: "Count",
    data() {
        return {
            n: 1 //用户选择的数字
        };
    },
    methods: {
        increment() {
            this.$store.commit("JIA", this.n);
        },
        decrement() {
            this.$store.commit("JIAN", this.n);
        },
        incrementOdd() {
            this.$store.dispatch("jiaOdd", this.n);
        },
        incrementWait() {
            this.$store.dispatch("jiaWait", this.n);
        }
    },
    mounted() {
        console.log("Count", this);
    }
};
</script>

<style lang="css">
button {
    margin-left: 5px;
}
* {
    margin-left: 30px;
}
</style>

3、main.js(下同)

//引入Vue
import Vue from "vue";
//引入App
import App from "./App.vue";

//引入store
import store from "./store";

//关闭Vue的生产提示
Vue.config.productionTip = false;

//创建vm
new Vue({
    el: "#app",
    render: (h) => h(App),
    store, // store配置项
    beforeCreate() {
        Vue.prototype.$bus = this;
    }
});

4、App.vue(下同)

<template>
	<div>
		<Count/>
	</div>
</template>

<script>
	import Count from './components/Count'
	export default {
		name:'App',
		components:{Count},
		mounted() {
			// console.log('App',this)
		},
	}
</script>

二、Vuex中的getters

1、store下的indx.js中加入如下配置

/*  
	适用于想要复用这些逻辑并且只针对state操作
*/
//准备getters——用于将state中的数据进行加工
const getters = {
    bigSum(state) {
        return state.sum * 10;
    }
};

2、使用

<h3>当前求和放大10倍为:{{$store.getters.bigSum}}</h3>

三、mapState和mapGetters

1、store文件夹下的index.js

//该文件用于创建Vuex中最为核心的store
import Vue from "vue";
//引入Vuex
import Vuex from "vuex";
//应用Vuex插件
Vue.use(Vuex);

//准备actions——用于响应组件中的动作
const actions = {
    /* jia(context,value){
		console.log('actions中的jia被调用了')
		context.commit('JIA',value)
	},
	jian(context,value){
		console.log('actions中的jian被调用了')
		context.commit('JIAN',value)
	}, */
    jiaOdd(context, value) {
        console.log("actions中的jiaOdd被调用了");
        if (context.state.sum % 2) {
            context.commit("JIA", value);
        }
    },
    jiaWait(context, value) {
        console.log("actions中的jiaWait被调用了");
        setTimeout(() => {
            context.commit("JIA", value);
        }, 500);
    }
};
//准备mutations——用于操作数据(state)
const mutations = {
    JIA(state, value) {
        console.log("mutations中的JIA被调用了");
        state.sum += value;
    },
    JIAN(state, value) {
        console.log("mutations中的JIAN被调用了");
        state.sum -= value;
    }
};
//准备state——用于存储数据
const state = {
    sum: 0, //当前的和
    school: "xxx大学",
    subject: "前端"
};
//准备getters——用于将state中的数据进行加工
const getters = {
    bigSum(state) {
        return state.sum * 10;
    }
};

//创建并暴露store
export default new Vuex.Store({
    actions,
    mutations,
    state,
    getters
});

2、Count.vue组件

<template>
    <div>
        <h1>当前求和为:{{ sum }}</h1>
        <h3>当前求和放大10倍为:{{ bigSum }}</h3>
        <h3>我在{{ school }},学习{{ subject }}</h3>
        <select v-model.number="n">
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>
        </select>
        <button @click="increment">+</button>
        <button @click="decrement">-</button>
        <button @click="incrementOdd">当前求和为奇数再加</button>
        <button @click="incrementWait">等一等再加</button>
    </div>
</template>

<script>
import { mapState, mapGetters } from "vuex";
export default {
    name: "Count",
    data() {
        return {
            n: 1 //用户选择的数字
        };
    },
    computed: {
        //靠程序员自己亲自去写计算属性(等同于...mapState(["sum", "school", "subject"]))
        /* 
			sum(){
				return this.$store.state.sum
			},
			school(){
				return this.$store.state.school
			},
			subject(){
				return this.$store.state.subject
			}, 
		*/

        //借助mapState生成计算属性,从state中读取数据。(对象写法)
        // ...mapState({he:'sum',xuexiao:'school',xueke:'subject'}),

        //借助mapState生成计算属性,从state中读取数据。(数组写法)
        /*  
			...的写法是因为mapState是一个对象,计算属性也是一个对象,
		  	不能在一个对象里直接写一个对象,所以用 ... 将对象展开放入计算属性中
		*/
        ...mapState(["sum", "school", "subject"]),

        /* ******************************************************************** */

        /* bigSum(){
				return this.$store.getters.bigSum
			}, */

        // 借助mapGetters生成计算属性,从getters中读取数据。(对象写法)
        // ...mapGetters({bigSum:'bigSum'})

        //借助mapGetters生成计算属性,从getters中读取数据。(数组写法)
        ...mapGetters(["bigSum"])
    },
    methods: {
        increment() {
            this.$store.commit("JIA", this.n);
        },
        decrement() {
            this.$store.commit("JIAN", this.n);
        },
        incrementOdd() {
            this.$store.dispatch("jiaOdd", this.n);
        },
        incrementWait() {
            this.$store.dispatch("jiaWait", this.n);
        }
    },
    mounted() {
        const x = mapState({ he: "sum", xuexiao: "school", xueke: "subject" });
        console.log(x);
    }
};
</script>

<style lang="css">
button {
    margin-left: 5px;
}
</style>

四、mapMutations和mapActions

1、store文件夹下index.js

//该文件用于创建Vuex中最为核心的store
import Vue from "vue";
//引入Vuex
import Vuex from "vuex";
//应用Vuex插件
Vue.use(Vuex);

//准备actions——用于响应组件中的动作
const actions = {
    /* jia(context,value){
		console.log('actions中的jia被调用了')
		context.commit('JIA',value)
	},
	jian(context,value){
		console.log('actions中的jian被调用了')
		context.commit('JIAN',value)
	}, */
    jiaOdd(context, value) {
        console.log("actions中的jiaOdd被调用了");
        if (context.state.sum % 2) {
            context.commit("JIA", value);
        }
    },
    jiaWait(context, value) {
        console.log("actions中的jiaWait被调用了");
        setTimeout(() => {
            context.commit("JIA", value);
        }, 500);
    }
};
//准备mutations——用于操作数据(state)
const mutations = {
    JIA(state, value) {
        console.log("mutations中的JIA被调用了");
        state.sum += value;
    },
    JIAN(state, value) {
        console.log("mutations中的JIAN被调用了");
        state.sum -= value;
    }
};
//准备state——用于存储数据
const state = {
    sum: 0, //当前的和
    school: "xxx大学",
    subject: "前端"
};
//准备getters——用于将state中的数据进行加工
const getters = {
    bigSum(state) {
        return state.sum * 10;
    }
};

//创建并暴露store
export default new Vuex.Store({
    actions,
    mutations,
    state,
    getters
});

2、Count.vue组件

<template>
    <div>
        <h1>当前求和为:{{ sum }}</h1>
        <h3>当前求和放大10倍为:{{ bigSum }}</h3>
        <h3>我在{{ school }},学习{{ subject }}</h3>
        <select v-model.number="n">
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>
        </select>
        <button @click="increment(n)">+</button>
        <button @click="decrement(n)">-</button>
        <button @click="incrementOdd(n)">当前求和为奇数再加</button>
        <button @click="incrementWait(n)">等一等再加</button>
    </div>
</template>

<script>
import { mapState, mapGetters, mapMutations, mapActions } from "vuex";
export default {
    name: "Count",
    data() {
        return {
            n: 1 //用户选择的数字
        };
    },
    computed: {
        //借助mapState生成计算属性,从state中读取数据。(对象写法)
        // ...mapState({he:'sum',xuexiao:'school',xueke:'subject'}),

        //借助mapState生成计算属性,从state中读取数据。(数组写法)
        ...mapState(["sum", "school", "subject"]),

        /* ******************************************************************** */

        //借助mapGetters生成计算属性,从getters中读取数据。(对象写法)
        // ...mapGetters({bigSum:'bigSum'})

        //借助mapGetters生成计算属性,从getters中读取数据。(数组写法)
        ...mapGetters(["bigSum"])
    },
    methods: {
        //程序员亲自写方法
        /* increment(){
				this.$store.commit('JIA',this.n)
			},
			decrement(){
				this.$store.commit('JIAN',this.n)
			}, */

        //借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(对象写法)
        ...mapMutations({ increment: "JIA", decrement: "JIAN" }),

        //借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(数组写法)
        // ...mapMutations(['JIA','JIAN']),

        /* ************************************************* */

        //程序员亲自写方法
        /* incrementOdd(){
				this.$store.dispatch('jiaOdd',this.n)
			},
			incrementWait(){
				this.$store.dispatch('jiaWait',this.n)
			}, */

        //借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(对象写法)
        ...mapActions({ incrementOdd: "jiaOdd", incrementWait: "jiaWait" })

        //借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(数组写法)
        // ...mapActions(['jiaOdd','jiaWait'])
    },
    mounted() {
        const x = mapState({ he: "sum", xuexiao: "school", xueke: "subject" });
        console.log(x);
    }
};
</script>

<style lang="css">
button {
    margin-left: 5px;
}
</style>

五、Vuex实现多组件通信

1、store文件夹下的index.js

//该文件用于创建Vuex中最为核心的store
import Vue from "vue";
//引入Vuex
import Vuex from "vuex";
//应用Vuex插件
Vue.use(Vuex);

//准备actions——用于响应组件中的动作
const actions = {
    /* jia(context,value){
		console.log('actions中的jia被调用了')
		context.commit('JIA',value)
	},
	jian(context,value){
		console.log('actions中的jian被调用了')
		context.commit('JIAN',value)
	}, */
    jiaOdd(context, value) {
        console.log("actions中的jiaOdd被调用了");
        if (context.state.sum % 2) {
            context.commit("JIA", value);
        }
    },
    jiaWait(context, value) {
        console.log("actions中的jiaWait被调用了");
        setTimeout(() => {
            context.commit("JIA", value);
        }, 500);
    }
};
//准备mutations——用于操作数据(state)
const mutations = {
    JIA(state, value) {
        console.log("mutations中的JIA被调用了");
        state.sum += value;
    },
    JIAN(state, value) {
        console.log("mutations中的JIAN被调用了");
        state.sum -= value;
    },
    ADD_PERSON(state, value) {
        console.log("mutations中的ADD_PERSON被调用了");
        state.personList.unshift(value);
    }
};
//准备state——用于存储数据
const state = {
    sum: 0, //当前的和
    school: "xxx大学",
    subject: "前端",
    personList: [{ id: "001", name: "张三" }]
};
//准备getters——用于将state中的数据进行加工
const getters = {
    bigSum(state) {
        return state.sum * 10;
    }
};

//创建并暴露store
export default new Vuex.Store({
    actions,
    mutations,
    state,
    getters
});

2、Count.vue插件

<template>
    <div>
        <h1>当前求和为:{{ sum }}</h1>
        <h3>当前求和放大10倍为:{{ bigSum }}</h3>
        <h3>我在{{ school }},学习{{ subject }}</h3>
        <h3 style="color:red">Person组件的总人数是:{{ personList.length }}</h3>
        <select v-model.number="n">
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>
        </select>
        <button @click="increment(n)">+</button>
        <button @click="decrement(n)">-</button>
        <button @click="incrementOdd(n)">当前求和为奇数再加</button>
        <button @click="incrementWait(n)">等一等再加</button>
    </div>
</template>

<script>
import { mapState, mapGetters, mapMutations, mapActions } from "vuex";
export default {
    name: "Count",
    data() {
        return {
            n: 1 //用户选择的数字
        };
    },
    computed: {
        //借助mapState生成计算属性,从state中读取数据。(数组写法)
        ...mapState(["sum", "school", "subject", "personList"]),
        //借助mapGetters生成计算属性,从getters中读取数据。(数组写法)
        ...mapGetters(["bigSum"])
    },
    methods: {
        //借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(对象写法)
        ...mapMutations({ increment: "JIA", decrement: "JIAN" }),
        //借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(对象写法)
        ...mapActions({ incrementOdd: "jiaOdd", incrementWait: "jiaWait" })
    },
    mounted() {
        // const x = mapState({he:'sum',xuexiao:'school',xueke:'subject'})
        // console.log(x)
    }
};
</script>

<style lang="css">
button {
    margin-left: 5px;
}
</style>

3、Person.vue插件

<template>
    <div>
        <h1>人员列表</h1>
        <h3 style="color:red">Count组件求和为:{{ sum }}</h3>
        <input type="text" placeholder="请输入名字" v-model="name" />
        <button @click="add">添加</button>
        <ul>
            <li v-for="p in personList" :key="p.id">{{ p.name }}</li>
        </ul>
    </div>
</template>

<script>
import { nanoid } from "nanoid";
export default {
    name: "Person",
    data() {
        return {
            name: ""
        };
    },
    computed: {
        personList() {
            return this.$store.state.personList;
        },
        sum() {
            return this.$store.state.sum;
        }
    },
    methods: {
        add() {
            const personObj = { id: nanoid(), name: this.name };
            this.$store.commit("ADD_PERSON", personObj);
            this.name = "";
        }
    }
};
</script>

六、Vuex模块化编码

在这里插入图片描述
在这里插入图片描述

count.js和person.js在数据少,数据简单的时候也可以写在index.js中

1、store文件夹下index.js

//该文件用于创建Vuex中最为核心的store
import Vue from "vue";
//引入Vuex
import Vuex from "vuex";
import countOptions from "./count";
import personOptions from "./person";
//应用Vuex插件
Vue.use(Vuex);

//创建并暴露store
export default new Vuex.Store({
    modules: {
        countAbout: countOptions,
        personAbout: personOptions
    }
});

2、store文件夹下count.js

//求和相关的配置
export default {
    namespaced: true,
    actions: {
        jiaOdd(context, value) {
            console.log("actions中的jiaOdd被调用了");
            if (context.state.sum % 2) {
                context.commit("JIA", value);
            }
        },
        jiaWait(context, value) {
            console.log("actions中的jiaWait被调用了");
            setTimeout(() => {
                context.commit("JIA", value);
            }, 500);
        }
    },
    mutations: {
        JIA(state, value) {
            console.log("mutations中的JIA被调用了");
            state.sum += value;
        },
        JIAN(state, value) {
            console.log("mutations中的JIAN被调用了");
            state.sum -= value;
        }
    },
    state: {
        sum: 0, //当前的和
        school: "xxx大学",
        subject: "前端"
    },
    getters: {
        bigSum(state) {
            return state.sum * 10;
        }
    }
};

3、store文件夹下person.js

//人员管理相关的配置
import axios from "axios";
import { nanoid } from "nanoid";
export default {
    namespaced: true,
    actions: {
        addPersonWang(context, value) {
            if (value.name.indexOf("王") === 0) {
                context.commit("ADD_PERSON", value);
            } else {
                alert("添加的人必须姓王!");
            }
        },
        addPersonServer(context) {
            axios.get("https://api.uixsj.cn/hitokoto/get?type=social").then(
                (response) => {
                    context.commit("ADD_PERSON", { id: nanoid(), name: response.data });
                },
                (error) => {
                    alert(error.message);
                }
            );
        }
    },
    mutations: {
        ADD_PERSON(state, value) {
            console.log("mutations中的ADD_PERSON被调用了");
            state.personList.unshift(value);
        }
    },
    state: {
        personList: [{ id: "001", name: "张三" }]
    },
    getters: {
        firstPersonName(state) {
            return state.personList[0].name;
        }
    }
};

4、Count.vue组件

<template>
    <div>
        <h1>当前求和为:{{ sum }}</h1>
        <h3>当前求和放大10倍为:{{ bigSum }}</h3>
        <h3>我在{{ school }},学习{{ subject }}</h3>
        <h3 style="color:red">Person组件的总人数是:{{ personList.length }}</h3>
        <select v-model.number="n">
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>
        </select>
        <button @click="increment(n)">+</button>
        <button @click="decrement(n)">-</button>
        <button @click="incrementOdd(n)">当前求和为奇数再加</button>
        <button @click="incrementWait(n)">等一等再加</button>
    </div>
</template>

<script>
import { mapState, mapGetters, mapMutations, mapActions } from "vuex";
export default {
    name: "Count",
    data() {
        return {
            n: 1 //用户选择的数字
        };
    },
    computed: {
        //借助mapState生成计算属性,从state中读取数据。(数组写法)
        // ...mapState(["countAbout","personAbout"]) //(使用:countAbout.sum,countAbout.school······)
        ...mapState("countAbout", ["sum", "school", "subject"]), //这种写法的前提是开启命名空间namespaced:true,(直接使用:sum,school·····)
        ...mapState("personAbout", ["personList"]),
        //借助mapGetters生成计算属性,从getters中读取数据。(数组写法)
        ...mapGetters("countAbout", ["bigSum"])
    },
    methods: {
        //借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(对象写法)
        ...mapMutations("countAbout", { increment: "JIA", decrement: "JIAN" }),
        //借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(对象写法)
        ...mapActions("countAbout", { incrementOdd: "jiaOdd", incrementWait: "jiaWait" })
    },
    mounted() {
        console.log(this.$store);
    }
};
</script>

<style lang="css">
button {
    margin-left: 5px;
}
</style>

5、Person.vue组件

<template>
    <div>
        <h1>人员列表</h1>
        <h3 style="color:red">Count组件求和为:{{ sum }}</h3>
        <h3>列表中第一个人的名字是:{{ firstPersonName }}</h3>
        <input type="text" placeholder="请输入名字" v-model="name" />
        <button @click="add">添加</button>
        <button @click="addWang">添加一个姓王的人</button>
        <button @click="addPersonServer">添加一个人,名字随机</button>
        <ul>
            <li v-for="p in personList" :key="p.id">{{ p.name }}</li>
        </ul>
    </div>
</template>

<script>
import { nanoid } from "nanoid";
export default {
    name: "Person",
    data() {
        return {
            name: ""
        };
    },
    computed: {
        personList() {
            return this.$store.state.personAbout.personList;
        },
        sum() {
            return this.$store.state.countAbout.sum;
        },
        firstPersonName() {
            return this.$store.getters["personAbout/firstPersonName"];
        }
    },
    methods: {
        add() {
            const personObj = { id: nanoid(), name: this.name };
            this.$store.commit("personAbout/ADD_PERSON", personObj);
            this.name = "";
        },
        addWang() {
            const personObj = { id: nanoid(), name: this.name };
            this.$store.dispatch("personAbout/addPersonWang", personObj);
            this.name = "";
        },
        addPersonServer() {
            this.$store.dispatch("personAbout/addPersonServer");
        }
    }
};
</script>
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

心醉瑶瑾前

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值