目录
一、目的
让代码更好维护,让多种数据分类更加明确
二、模块化应用
2.1 store.js直接应用模块化
// 引入Vue核心库
import Vue from "vue";
// 引入Vuex
import Vuex from "vuex";
// 应用Vuex插件
Vue.use(Vuex);
// 模块1相关的配置
const 模块名1 = {
namespace:true, // 开启命名空间
state:{...},
actions:{...},
mutations:{...},
getters:{...}
}
// 模块2相关的配置
const 模块名2 = {
namespace:true, // 开启命名空间
state:{...},
actions:{...},
mutations:{...},
getters:{...}
}
export default new Vuex.Store({
modules:{
自定义模块命名1:模块名1,
自定义模块命名2:模块名2,
}
})
2.2 store.js 外部引入
让 store.js 更加精简,维护只需要去对应的外部文件
例如:
store外部文件:模块1.js
// 模块1相关配置
export default {
namespace:true, // 开启命名空间
state:{...},
actions:{...},
mutations:{...},
getters:{...}
}
store外部文件:模块2.js
// 模块2相关配置
export default {
namespace:true, // 开启命名空间
state:{...},
actions:{...},
mutations:{...},
getters:{...}
}
store.js 引入 模块1.js 和 模块2.js
// 引入Vue核心库
import Vue from "vue";
// 引入Vuex
import Vuex from "vuex";
// 引入模块1.js
import 模块名1 from "./模块1.js";
// 引入模块2.js
import 模块名2 from "./模块2.js";
// 应用Vuex插件
Vue.use(Vuex);
export default new Vuex.Store({
modules:{
自定义模块命名1:模块名1,
自定义模块命名2:模块名2,
}
})
三、开启命名空间后的读取与调用
3.1 state数据
开启命名空间后,组件读取state数据:
// 方式一:自己直接读取, dataName代指state内自己命名的数据
this.$store.state.自定义模块命名.dataName
.....
// 方式二:借助mapState读取
...mapState('自定义模块命名',['dataName','...','...'])
3.2 getters数据
开启命名空间后,组件读取getters数据:
// 方式一:自己直接读取, dataName代指getters内自己命名的数据
this.$store.getters['自定义模块命名/dataName']
.....
// 方式二:借助mapGetters读取
...mapGetters('自定义模块命名',['dataName','...','...'])
3.3 调用dispatch
开启命名空间后,组件中调用dispatch:
// 方式一:自己直接dispatch, data代值传入的数据
this.$store.dispatch('自定义模块命名/actions中方法名', data)
.....
// 方式二:借助mapActions
...mapActions('自定义模块命名',{事件1: "actions中方法名1", 事件2: "actions中方法名2",...})
3.4 调用commit
开启命名空间后,组件中调用commit:
// 方式一:自己直接commit, data代值传入的数据名
this.$store.commit('自定义模块命名/mutations中方法名', data)
.....
// 方式二:借助mapMutations
...mapMutations('自定义模块命名',{事件1: "mutations方法1", 事件2: "mutations方法2",...})
四、案例练习
以 Vue知识点整理(五)- vuex(2)中 第三节 多组件数据共享 案例 为基础
4.1 count.js
将 求和组件相关 的 store配置项封装到count.js中
// 求和相关的配置
export default {
namespaced: true,
actions: {
add(context, value) {
context.commit("ADD", value);
},
sub(context, value) {
context.commit("SUB", value);
},
addOdd(context, value) {
if (context.state.sum % 2) {
context.commit("ADD", value);
}
},
addWait(context, value) {
setTimeout(() => {
context.commit("ADD", value);
}, 1000);
},
},
mutations: {
ADD(state, value) {
state.sum += value;
},
SUB(state, value) {
state.sum -= value;
},
},
state: {
sum: 0,
},
getters: {
bigSum(state) {
return state.sum * 10;
},
},
};
4.2 game.js
将 游戏列表组件相关 的 store配置项封装到game.js中,其中actions中添加了"addE"事件相关内容以及addNameServer事件联系后端API发送请求(异步事件),访问免费小语录API;getters中存放了 firstGameName数据 - 用于显示当前列表第一个的数据名
import axios from "axios";
import { nanoid } from "nanoid";
// 游戏列表相关的配置
export default {
namespaced: true,
actions: {
addE(context, value) {
if (value.name.indexOf("E") === 0) {
context.commit("ADD_GAME", value);
} else {
alert("添加的游戏必须带有大写字母E");
}
},
addNameServer(context) {
axios.get("https://api.uixsj.cn/hitokoto/get?type=social").then(
(response) => {
context.commit("ADD_GAME", { id: nanoid(), name: response.data });
console.log(response);
},
(error) => {
alert(error.message);
}
);
},
},
mutations: {
ADD_GAME(state, value) {
state.gameList.unshift(value);
},
},
state: {
gameList: [{ id: "001", name: "Splatoon3" }],
},
getters: {
firstGameName(state) {
return state.gameList[0].name;
},
},
};
4.3 index.js - store配置
引入了 count.js模块 和 game.js模块 并命名
// 引入Vue核心库
import Vue from "vue";
// 引入Vuex
import Vuex from "vuex";
// 应用Vuex插件
Vue.use(Vuex);
import countOption from "./count";
import gameOption from "./game";
// 创建并暴露store
export default new Vuex.Store({
modules: {
countAbout: countOption,
gameAbout: gameOption,
},
});
4.4 Game.vue
添加了 addE事件 和 addNameServer事件相关按钮,并修改了开启命名空间后的state、getters的读取与actions、mutations的调用
<template>
<div style="padding: 20px">
<h1>游戏列表</h1>
<input type="text" placeholder="请输入游戏名" v-model="name" />
<button @click="add">添加</button>
<button @click="addE">添加含大写字母E的游戏</button>
<button @click="addNameServer">添加Server生成语录</button>
<h3>上方Count组件求和为:{{ sum }}</h3>
<h3>列表中第一个数据是:{{ firstGameName }}</h3>
<ul>
<li v-for="g in gameList" :key="g.id">{{ g.name }}</li>
</ul>
</div>
</template>
<script>
import { mapState } from "vuex";
// 引入nanoid-第三方
import { nanoid } from "nanoid";
export default {
name: "Game",
data() {
return {
name: "",
};
},
computed: {
...mapState("gameAbout", ["gameList"]),
sum() {
return this.$store.state.countAbout.sum;
},
firstGameName() {
return this.$store.getters["gameAbout/firstGameName"];
},
},
methods: {
add() {
const gameObj = { id: nanoid(), name: this.name };
this.$store.commit("gameAbout/ADD_GAME", gameObj);
this.name = "";
},
addE() {
const gameObj = { id: nanoid(), name: this.name };
this.$store.dispatch("gameAbout/addE", gameObj);
this.name = "";
},
addNameServer() {
this.$store.dispatch("gameAbout/addNameServer");
},
},
};
</script>
<style></style>
4.5 Count.vue
修改了开启命名空间后的state、getters的读取与actions、mutations的调用
<template>
<div style="padding: 20px">
<h1>当前求和为:{{ sum }}</h1>
<!-- 模板中添加一个需要引入加工数据的模块 -->
<h3>当前求和放大10倍为:{{ bigSum }}</h3>
<h3>下方组件游戏个数:{{ gameList.length }}</h3>
<select v-model="n">
<option :value="1">1</option>
<option :value="2">2</option>
<option :value="3">3</option>
</select>
<!-- 注意:mapActions 与 mapMutations,若需要传递参数则需要:在模板中绑定事件时传递好参数,否则参数是事件对象 -->
<button @click="increment(n)">+</button>
<button @click="decrement(n)">-</button>
<button @click="incrementOdd(n)">当前求和为奇数再加</button>
<button @click="incrementWait(n)">等1s后再加</button>
</div>
</template>
<script>
// 引入mapState, mapGetters, mapActions, mapMutations
import { mapState, mapGetters, mapActions, mapMutations } from "vuex";
export default {
name: "Count",
data() {
return {
n: 1, // 用户选择的数字
};
},
computed: {
// 借助mapState生成计算属性 - 数组写法
...mapState("countAbout", ["sum"]),
...mapState("gameAbout", ["gameList"]),
// 借助mapGetters生成计算属性 - 对象写法
...mapGetters("countAbout", { bigSum: "bigSum" }),
},
methods: {
// 靠mapMutations生成与mutations对话的方法 - 对象形式
...mapMutations("countAbout", { increment: "ADD", decrement: "SUB" }),
// 靠mapActions生成与actions对话的方法 - 对象形式
...mapActions("countAbout", {
incrementOdd: "addOdd",
incrementWait: "addWait",
}),
},
};
</script>
<style></style>