写在前面
大佬建议不看本文,太基础了。本文适合初学者,便于理解。
基本上都是大白话,有耐心的同学可以读完,这样vuex基本上你就可以使用了。
可能有一些同学在自己的学习过程中在用vuex,但是只是在用state。
今天我想用纯手写的方式和大家一起再学习一次vuex。如有表述错误,请各位大佬多多指正。
一、mutation
兄弟组件通讯的例子
我们来看一下这样一个例子。
父组件:
<template>
<div>
<A @onChangeMsg="onChangeMsg"></A>
<B :messageB="message"></B>
</div>
</template>
<script>
import A from './A';
import B from './B';
export default {
data() {
return {
message: ""
}
},
components: {
A,
B
},
methods: {
onChangeMsg(val) {
this.message = val;
}
},
}
</script>
子组件A
<template>
<div>
<div>
{{ messageA }}
</div>
<button @click="changMsg">按钮</button>
</div>
</template>
<script>
export default {
data() {
return {
messageA: "我是messageA"
}
},
methods: {
changMsg() {
this.$emit("onChangeMsg", this.messageA)
}
},
}
</script>
<style lang="scss" scoped>
</style>
子组件B
<template>
<div>
<div>
{{ messageB }}
</div>
</div>
</template>
<script>
export default {
props: {
messageB: {
type: String,
default: ""
}
}
}
</script>
<style lang="scss" scoped>
</style>
描述:
现在呢,有这样一种情形,组件A和组件B是兄弟组件,这点大家都能看出来。
组件B要得到组件A的传值。怎么做呢? 有一种方式就像我上面举得这个例子一样。
组件A通过绑定事件onChangeMsg,传递一个值messageA给父组件,父组件接收到这个值后,来改变父组件中的message。这就是我们向上传值的一种方式。
这时候父组件又通过props的方式,传值给组件B。组件B通过props接收到了父组件传来的值。
这样组件B就拿到了组件A的值。其实这里的父组件就是一个桥梁的作用,为组件A和组件B的通讯搭了个桥。但是呢,这里有一个很麻烦的点就是一个字传了两次才到目的地。
那怎样才能一次就到子组件呢? 有的同学可能会用事件总线的方式EventBus.但是我不建议使用这种方式,因为难以维护,写的很乱。
现在我们的vuex就可以派上用场了。
mutation:
我们先看一下vuex里面怎么写吧。
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.store({
state: {
message: ""
},
mutations: {
setMessage(state, val) {
state.message = val;
}
}
})
state里面的message就是我们的共享数据了。所有组件都可以拿到他。
这时候我们传值就非常简单了。当我们想要取值的时候。用到vuex里面的mapState
在computed中
computed:{ ...mapState(["message"]) }
这样我们就取到值了
我们还可以拿到mutation中的方法
应用vuex中的mapMutation,在method中
method: {
...mapMutation(["setMessage"])
}
这样我们就可以在改变change值的时候,调用setMessage方法,把改变的值传过去就可以改变vuex中的state值了。
是不是很方便呢?
到这里大家就应该明白,vuex中的mutation是怎么使用的了。
当然我们对于mutation还有其他写法。
this.store.commit("setMessage", "我是传值");
这样呢,是用commit调用setMessage。
这样是一样的。当我们需要传多个值的时候。
this.store.commit("setMessage", { val1,val2 });
大家可以把mutation理解成是更改state的。
二、getters
getters就是可以进一步的处理state。
就比如我不想直接返回state的,我想vuex先把state给我处理好。
我想返回一句话,这一句话中呢,包含了state。这在mutation中是做不到的。
getters: {
getMsgInfo (state) {
return `这是父组件返回了的信息————${state.message}`;
}
}
这样我们就处理好了。就可以直接在我们的组件中,拿到这一串值。
怎么用呢?
mounted() {
this.getterMsg = this.$store.getters.getMsgInfo;
},
这里的getterMsg是在组件中定义的data。
所以我们在想要加工state,就可以使用state。比如一些计算呢,就可以使用getters。
三、actions
记住一句话,异步就用actions。
actions拿到的返回值,传给mutation赋值给state。很好理解。
来,上代码,理解过程
actions:
actions: {
getData (ctx, payload) {
axios({
url: "api/data",
data: {
...payload
}
}).then(
res => {
ctx.commit("setData", res.data);
}
)
}
}
mutation:
mutations: {
setData(state, data) {
state.data = data;
}
},
组件调用actions中的方法:
mounted() {
this.$store.dispatch("getData", {
id,name,sex,date
})
},
这就是一套完整的流程。是不是很简单呢?
四、moudules
当然我们在实际项目中,需要模块化的去管理state。
怎么做?
来,上才艺!
![e1582a260aa5d0fb338f440dec6a65c6.png](https://i-blog.csdnimg.cn/blog_migrate/ed3680a2ec8e461b50be5d0f52690934.png)
我们在store里面创建一个文件夹moudules.
在moudles中,存放不通模块的处理逻辑。举个例子:
moudules里面放home.js、list.js、login.js
这三个文件呢,里面的结构我们可以这样写:
const state = {};
const getters = {};
const mutations = {};
const actions = {};
export default {
// namespaced: true, 这个属性大家自己百度吧,防止命名冲突
state,
actions,
mutations
};
那index.js就很简单了:
import Vue from "vue";
import Vuex from "vuex";
import login from "./modules/login";
import list from "./modules/common";
import home from "./modules/common";
Vue.use(Vuex);
export default new Vuex.Store({
modules: { login, list, home}
});
这样维护起来是不是就很方便了呢?
最后不要忘了在main.js中引入store。