Vuex
1. 什么是vuex?
专门在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信
2. 什么时候使用vuex?
- 多个组件依赖于同一个状态(数据)
- 来自不同组件的行为需要变更同一状态(数据)
3. 搭建开发环境
下载安装vuex npm i vuex
在src文件夹下创建 store/index.js
// 该文件用于创建Vuex中最为核心的store
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
// 准备actions,用于响应组件中的动作
const actions = {};
// 准备mutations,用于操作数据(state)
const mutations = {};
// 准备state,用于存储数据
const state = {};
// 创建store
export default new Vuex.Store({ actions, mutations, state });
在 main.js 中引入并配置 store
import store from "./store";
new Vue({
store,
render: (h) => h(App),
}).$mount("#app");
配置完成后,vm以及所有的vc都有 $store
属性
4. 案例
Count.vue
<template>
<div>
<!-- 将数据从store中取出 -->
<h1>当前求和为:{{ $store.state.total }}</h1>
<select v-model.number="val">
<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 {
val: 1,
};
},
methods: {
increment() {
// 如果不需要特殊的业务逻辑,可以跳过dispatch直接进行commit
this.$store.commit("ADD", this.val);
},
decrement() {
this.$store.commit("SUB", this.val);
},
incrementOdd() {
this.$store.dispatch("addOdd", this.val);
},
incrementWait() {
this.$store.dispatch("addWait", this.val);
},
},
};
</script>
<style scoped>
button {
margin-left: 8px;
}
</style>
store/index.js
// 准备actions,用于响应组件中的动作
const actions = {
// 在context中也有dispatch,可以继续分发
add(context, value) {
console.log("actions中的add被调用了...");
console.log(context, value);
context.commit("ADD", value);
},
sub(context, value) {
context.commit("SUB", value);
},
addOdd(context, value) {
if (context.state.total % 2 === 1) {
context.commit("ADD", value);
}
},
addWait(context, value) {
setTimeout(() => {
context.commit("ADD", value);
}, 1000);
},
};
// 准备mutations,用于操作数据(state)
const mutations = {
ADD(state, value) {
console.log("mutations中的ADD被调用了...");
console.log(state, value);
state.total += value;
},
SUB(state, value) {
state.total -= value;
},
};
// 准备state,用于存储数据
const state = {
total: 0,
};
流程:将数据交给state来保管,组件提出数据的处理请求(dispatch),由actions中对应的函数接收,进行一些业务逻辑的处理后,交给mutations进行数据的修改等操作(commit)
5. 其他
getters:用于将state中的数据进行加工(类似计算属性)
const getters = {
bigTotal(state) {
return state.total * 10;
},
};
组件中使用方式: $store.getters.bigTotal
通过映射从store中读取内容
<template>
<div>
<h1>当前求和为:{{ total }}</h1>
<h3>当前求和放大10倍为:{{ bigTotal }}</h3>
<h3>我是{{ name }},我今年{{ age }}岁</h3>
</div>
</template>
<script>
import { mapState, mapGetters } from "vuex";
export default {
computed: {
// 借助mapState生成计算属性,从state中读取数据
// 对象写法
// ...mapState({ total: "total", name: "name", age: "age" }),
// 数组写法
...mapState(["total", "name", "age"]),
// 借助mapGetters生成计算属性,从getters中读取数据,写法与mapState相同
...mapGetters(["bigTotal"]),
},
};
</script>
<template>
<div>
<!-- 如果不传参数,参数就是默认的事件对象 -->
<button @click="increment(val)">+</button>
<button @click="decrement(val)">-</button>
<button @click="incrementOdd(val)">当前求和为奇数再加</button>
<button @click="incrementWait(val)">等一等再加</button>
</div>
</template>
<script>
import { mapState, mapGetters, mapActions, mapMutations } from "vuex";
export default {
methods: {
// 生成对应方法调用dispatch和commit,写法与mapState一致
...mapMutations({ increment: "ADD", decrement: "SUB" }),
...mapActions({ incrementOdd: "addOdd", incrementWait: "addWait" }),
},
};
</script>
6. vuex 模块化
count.js
export default {
// 开启命名空间
namespaced: true,
actions: {
addOdd(context, value) {
if (context.state.total % 2 === 1) {
context.commit("ADD", value);
}
},
addWait(context, value) {
setTimeout(() => {
context.commit("ADD", value);
}, 1000);
},
},
mutations: {
ADD(state, value) {
state.total += value;
},
SUB(state, value) {
state.total -= value;
},
},
state: {
total: 0,
name: "LMY",
age: 25,
},
getters: {
bigTotal(state) {
return state.total * 10;
},
},
};
book.js
export default {
namespaced: true,
actions: {
insertBook(context, value) {
let book = {
id: nanoid(4),
name: value,
};
context.commit("INSERT_BOOK", book);
},
},
mutations: {
INSERT_BOOK(state, value) {
state.books.push(value);
},
},
state: { books: [{ id: "001", name: "默读" }] },
getters: {},
};
store/index.js
import countOptions from "./count";
import bookOptions from "./book";
export default new Vuex.Store({
modules: { countOptions, bookOptions },
});
在组件中应用的方式:要先开启命名空间 namespaced: true
...mapState("countOptions", ["total", "name", "age"])
this.$store.state.countOptions.total
...mapGetters("countOptions", ["bigTotal"])
this.$store.getters['countOptions/bigTotal']
...mapMutations("countOptions", { increment: "ADD", decrement: "SUB" })
this.$store.commit('countOptions/ADD', value)
...mapActions("countOptions", { incrementOdd: "addOdd", incrementWait: "addWait", }),
this.$store.dispatch('countOptions/addOdd', value)
模块化让代码更好维护,让多种数据分类更加明确