vuex基础结构
代码结构
vuex的完整结构长这样,其包含了state、mutations、actions、modules及getters5个部分。
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {},
mutations: {},
actions:{},
modules:{},
getters:{}
})
new Vue({
el: '#app',
})
假设我们在上述store内补充一些方法
const store = new Vuex.Store({
state: {
count:0
},
mutations: {
add(state){
state.count ++
}
},
actions:{},
modules:{},
getters:{}
})
现在,我们可以采用store.commit(‘add’) 的方式来更改count的值。
为了在其他vue组件中使用 this.$store 访问,我们可以这么做:
new Vue({
el: '#app',
store: store,
})
项目结构
为了使项目结构更加清晰,我们一般这么定义结构
├─ src
│ ├─ App.vue
│ ├─ main.js
│ └─ store
│ └─ index.js
// index.js
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
count: 0,
},
getters: {},
mutations: {
add(state) {
state.count++;
},
},
actions: {},
modules: {},
});
// main.js
import Vue from "vue";
import App from "./App.vue";
import store from "./store";
Vue.config.productionTip = false;
new Vue({
store,
render: (h) => h(App),
}).$mount("#app");
如果modules比较多,我们还可以在创建一个文件夹用来存放,比如在store下创建moduleA文件夹,我们在moduleA内创建index.js,并写入一些内容:
export default {
state: {},
getters: {},
mutations: {},
actions: {},
};
然后store根目录的index.js可以改写
import Vue from "vue";
import Vuex from "vuex";
import moduleA from "./moduleA/index";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
count: 0,
},
getters: {},
mutations: {
add(state) {
state.count++;
},
},
actions: {},
modules: {
moduleA: moduleA,
},
});
state的访问
state的方法有两种,一种是采用this.$store直接访问,另一种是借助mapState ****辅助函数。
this.$store访问
在上图中,我们可以看到this.$store上存在state属性,我们可以展开看看
很明显,通过this.$store.count可以直接访问到
mapState 辅助函数
import { mapState } from "vuex"; //引入方法
export default {
name: "App",
computed: {
...mapState(["count"]), // 注意这里是数组
},
};
Mutation的触发
我们知道Mutation中的函数是用来更改state中某个属性的状态的,如下面的代码
export default new Vuex.Store({
state: {
text: 0,
},
mutations: {
// mutations函数有两个参数,第一个参数是 state ,第二个参数是传递进来的值
changeText(state, payload) {
state.text = payload;
},
},
});
它有两种调用方式:
通过this.$store触发
methods: {
// 在函数中直接使用
changeBtn1() {
this.$store.commit("changeText", "你好,世界");
},
},
通过mapMutations辅助函数
// 1.引入mapMutations函数
import { mapMutations } from "vuex";
methods: {
// 2.在methods中使用拓展运算符展开函数
...mapMutations(["changeText"]),
// 3.调用阿含糊
changeBtn2() {
this.changeText("鱿鱼须懂个锤子vue");
},
},
代码演示
<template>
<div id="app">
<div>text的内容是: {{ text }}</div>
<button @click="changeBtn1">this.$store.commit更改</button>
<button @click="changeBtn2">mapMutations更改</button>
</div>
</template>
<script>
import { mapState, mapMutations } from "vuex";
export default {
name: "App",
computed: {
...mapState(["text"]),
},
methods: {
...mapMutations(["changeText"]),
changeBtn1() {
this.$store.commit("changeText", "你好,世界");
},
changeBtn2() {
this.changeText("鱿鱼须懂个锤子vue");
},
},
};
</script>
Action的触发
Action的触发方式同Mutation,它可以用来执行异步函数
export default new Vuex.Store({
state: {
text: 0,
},
mutations: {
// mutations函数有两个参数,第一个参数是 state ,第二个参数是传递进来的值
changeText(state, payload) {
state.text = payload;
},
},
actions: {
laterChange(context, value) {
setTimeout(() => {
context.commit("changeText", value);
}, 1000);
},
},
});
通过this.$store触发
methods: {
// 在函数中直接使用
changeBtn1() {
this.$store.dispatch("laterChange", "你好,世界");
},
},
通过mapActions辅助函数
// 1.引入mapActions函数
import {mapActions } from "vuex";
methods: {
// 2.在methods中使用拓展运算符展开函数
...mapMutations(["laterChange"]),
// 3.调用阿含糊
changeBtn2() {
this.laterChange("鱿鱼须懂个锤子vue");
},
},
代码演示
<template>
<div id="app">
<div>text的内容是: {{ text }}</div>
<button @click="changeBtn1">this.$store.dispatch更改</button>
<button @click="changeBtn2">mapActions更改</button>
</div>
</template>
<script>
import { mapState, mapActions, } from "vuex";
export default {
name: "App",
computed: {
...mapState(["text"]),
},
methods: {
...mapActions(["laterChange"]),
changeBtn1() {
this.$store.dispatch("laterChange", "你好,世界");
},
changeBtn2() {
this.laterChange("鱿鱼须懂个锤子vue");
},
},
};
</script>
actions函数的context参数
context有若干参数,如下
- 通过dispatch可以直接调用action平级内的函数
- 通过commit可以调用mutations内的函数
- 通过getters可以直接访问当前模块内的getters属性值
- 通过state可以访问当前模块内的state属性值
- 通过rootState可以访问根节点内的state属性值
- 通过rootGetters可以访问根节点内的getters属性值
实际开发中,利用解构赋值可以优化代码:
actions: {
laterChange({ dispatch, commit }, value) {
setTimeout(() => {
commit("changeText", value);
}, 1000);
},
},
Module
当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
为了解决以上问题,Vuex 允许我们将 store 分割成模块(module) 。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块。
export default new Vuex.Store({
state: {},
mutations: {},
actions: {},
getters: {},
modules: {
moduleA: {
// 是否开启命名空间
namespaced: true,
state: { count: 0 },
getters: {},
mutations: {
add(state, payload) {
state.count += payload;
},
},
actions: {
sub({ state, commit }, payload) {
commit("add", payload);
},
},
},
},
});
state数据访问
// 方法一
this.$store.state.moduleA.count
// 方法二 需要模块开启命名空间,不开启会报错
computed: {
...mapState("moduleA", ["count"]),
},
不开启命名空间的时候,只能使用方式一,开启后两种方式都可以使用
Mutation的调用
// 方法一
this.$store.commit("moduleA/add", "自定义value");
// 方法二 需要模块开启命名空间,不开启会报错
methods: {
...mapMutations("moduleA", ["add"]),
changeBtn1() {
this.add("自定义value");
},
},
Action的调用
// 方法一
this.$store.dispatch("moduleA/sub", "自定义value");
// 方法二 需要模块开启命名空间,不开启会报错
methods: {
...mapActions("moduleA", ["sub"]),
changeBtn1() {
this.sub("自定义value");
},
},