安装vuex
npm install vuex --save
main.js
//引入Vue
import Vue from "vue";
//引入App
import App from "./App.vue";
// 引入store
import store from "./store";
//关闭Vue的生产提示
Vue.config.productionTip = false;
// 引入vuex之后就Vm中就有一个store属性了
//创建vm
new Vue({
el: "#app",
render: h => h(App),
store
});
store.js
import Vuex from "vuex";
import Vue from "vue";
// --------- Vuex原理的三剑客
const actions = {
incrementOdd(context, value) {
if (context.state.sum % 2) {
context.commit("INCREMENT", value);
}
},
incrementWait(context, value) {
setTimeout(() => {
context.commit("INCREMENT", value);
}, 500);
}
};
const mutations = {
INCREMENT(state, value) {
state.sum += value;
},
DECREMENT(state, value) {
state.sum -= value;
}
};
// 类似于组件中的data,数据源
const state = {
sum: 1
};
// 类似于组件的计算属性,可在多个组件中复用的计算属性
const getters = {
bigSum(state) {
return state.sum * 10;
}
};
// ---------
// 在这里声明使用插件,而不在main.js中引用
/* 因为在main.js中引用,模块化的代码执行顺序是先执行import外部模块代码,在执行自己模块的代码,在main.js中引用该store/index.js模块时,
没有先声明Vuex,那么在执行import store from './store' 时解析到调用了new Vuex.Store,但是main.js中的使用插件Vue.use(Vuex)代码执行在import后面*/
Vue.use(Vuex);
export default new Vuex.Store({
actions,
mutations,
state,
getters
});
Count.vue
<template>
<div>
<h1>当前求和为:{{$store.state.sum}}</h1>
<h2>当前求和结果放大十倍是: {{$store.getters.bigSum}}</h2>
<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("INCREMENT", this.n);
},
decrement() {
this.$store.commit("DECREMENT", this.n);
},
incrementOdd() {
this.$store.dispatch("incrementOdd", this.n);
},
incrementWait() {
this.$store.dispatch("incrementWait", this.n);
}
}
};
</script>
<style lang="css">
button {
margin-left: 5px;
}
</style>
Vuex 辅助函数
mapState 与 mapGetters
当我们需要读取 store 中 state 的数据,我们需要多次书写this.$store.state
,代码冗余,这时可以使用 mapState 来快速获取 state 中的数据
mapGetters 同理
import { mapState, mapGetters } from "vuex";
export default {
computed: {
// ------自己写计算属性
// sum(){
// return this.$store.state.sum
// },
// bigSum(){
// return this.$store.getters.bigSum
// }
// ------
// 生成计算属性对象写法
// ...mapState({sum:'sum'}),
// 数组写法
...mapState(["sum"]),
// ...mapGetters({bigSum:'bigSum'})
...mapGetters(["bigSum"])
}
};
mapMutations 与 mapActions
<template>
<button @click="increment(n)">+</button>
<button @click="decrement(n)">-</button>
<button @click="incrementOdd(n)">当前求和为奇数再加</button>
<button @click="incrementWait(n)">等一等再加</button>
</template>
export default {
methods: {
/* increment() {
this.$store.commit("INCREMENT",this.n)
},
decrement() {
this.$store.commit("DECREMENT",this.n)
}, */
// 会自动接收页面中{{increment}}接收的参数,如果页面中不传,那么会接收到event事件参数
...mapMutations({ increment: "INCREMENT", decrement: "DECREMENT" }),
/* incrementOdd() {
this.$store.dispatch("incrementOdd", this.n);
},
incrementWait() {
this.$store.dispatch("incrementWait", this.n);
} */
// ...mapActions({incrementOdd:'incrementOdd',incrementWait:'incrementWait'})
// 如果函数名和后面的通信参数相同可以使用数组
...mapActions(["incrementOdd", "incrementWait"])
}
};
namespace\modules
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: {
countOptions,
personOptions
}
});
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: "尚硅谷",
subject: "前端"
},
getters: {
bigSum(state) {
return state.sum * 10;
}
}
};
``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;
}
}
};
vuex的目录结构
├── index.html
├── main.js
├── api
│ └── ... # 抽取出API请求
├── components
│ ├── App.vue
│ └── ...
└── store
├── index.js # 我们组装模块并导出 store 的地方
├── actions.js # 根级别的 action
├── mutations.js # 根级别的 mutation
└── modules
├── cart.js # 购物车模块
└── products.js # 产品模块