文章目录
一、Vuex是什么?
引用Vuex官网原话:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
通俗一点:它相当于一个管理数据的仓库,存放着各种需要共享的数据,所有的组件可以从中拿走数据。
基于Vuex能够更好地在组件外部管理状态,因此赋予了前端工程师使用Vuex构建一个中大型单页应用的能力。
二、Vuex的使用
1.安装
vue2项目中安装第三版本:npm i vuex@3
vue3项目中安装第四版本:npm i vuex@4
如果使用:npm i vuex 不指定版本数将默认安装最新版本
2.实例化store
新建store(状态)文件夹,在改文件夹下新建index.js文件
// 该文件用于创建Vuex中最为核心的store
// 引入Vue
import Vue from 'vue';
// 引入Vuex
import Vuex from 'vuex';
// 应用Vuex插件
Vue.use(Vuex);
// 准备actions——用于响应组件中的动作
const actions = {}
// 准备mutations——用于操作数据
const mutations = {}
// 准备state——用于存储公共数据
const state = {}
// getters——用于将state中的数据进行加工
const getters = {}
// 使用Vuex插件
Vue.use(Vuex);
// 创建并导出store
export default new Vuex.Store({
actions,
mutations,
state,
getters
});
3.在Vue实例中注入store
//省略...
import store from "./store/index" // 引入store
new Vue({
//省略...
store // 注入Vue实例———Vue实例对象中拥有$store属性
});
三、Vuex核心
1.State
state(译为:状态),用于存储公共数据,供组件取用
举个栗子:
// index.js
// state——用于存储数据
const state = {
school: 'ZZULI',
name: 'JV_32',
}
// Info组件
<template>
<div>
<h2>School:{{ school }}</h2>
<h2>Name:{{ name }}</h2>
</div>
</template>
<script>
export default {
name: "Info",
// 通过计算属性访问组件实例对象上的$store属性,读取state中的数据
computed: {
school() {
return this.$store.state.school;
},
name() {
return this.$store.state.name;
},
},
};
</script>
mapState()
通过使用Vuex定义的工具函数mapState(),把公共数据映射到组件内部的计算属性中,就不再需要多次通过return返回从store中读取的数据了
- mapState()的工作结果返回的是一个对象
- computed配置项为对象声明格式,因此在其中使用mapState()需要使用ES6对象拓展运算符 ...ES6对象拓展运算符
https://www.bookstack.cn/read/es6-3rd/spilt.6.docs-object.md
// 导入辅助函数mapState
import { mapState } from "vuex";
export default {
name: "Info",
computed: {
// school() {
// return this.$store.state.school;
// },
// name() {
// return this.$store.state.name;
// },
// 对象写法: mapState({ 计算属性1: "state数据属性1", 计算属性2: "state数据属性2" })
...mapState({ school: "school", name: "name" }),
// 数组写法: mapState([ "state数据属性1", "state数据属性2" ]),当组件中的计算属性与state中的数据属性同名时
...mapState(["school", "name"]),
},
2.Getter
相当于组件中的computed计算属性,对state中的数据进行加工
举个栗子:
// index.js
// state——用于存储公共数据
const state = {
school: 'ZZULI',
name: 'JV_32',
age: 20
}
// getters——用于将state中的数据进行加工
const getters = {
AddAge(state) { // 第一个参数为state对象
return state.age += 2;
}
}
//Info组件
<template>
<div>
// 省略...
<h3>Age:{{ AddAge }}</h3>
</div>
</template>
<script>
export default {
name: "Info",
// 通过计算属性访问组件实例对象上的$store属性,读取getters中的数据
computed: {
AddAge() {
return this.$store.getters.AddAge;
},
...mapState(["school", "name"]),
},
};
</script>
运行结果:
mapGetters()
同理,通过使用Vuex定义的工具函数mapGetters(),映射getters中的数据到计算属性中
// 导入辅助函数mapGetters
import { mapState, mapGetters } from "vuex";
export default {
name: "Info",
computed: {
...mapGetters(["AddAge"]),
...mapState(["school", "name"]),
},
};
3.Action
类似于组件中的methods配置项,用于响应组件中的动作,如:发送异步请求:Ajax等
举个栗子:
在组件中通过:this.$store.dispatch("请求的动作", 载荷) 来触发Action
export default {
name: "Info",
data() {
return {
n: 1,
};
},
methods: {
// 按钮的点击事件handler,负责向action请求increment动作
handler() {
this.$store.dispatch("increment", this.n);
},
},
};
在action中响应请求的动作increment
increment动作是一个函数:increment(context, params),context对象与store实例具有相同的方法和属性
- 因此你可以通过context.state或者context.getters获取state和getters中的数据
- 也可以通过context.commit()来触发Mutation,从而对state或getter中的数据进行操作
// 准备actions——用于响应组件中的动作
const actions = {
increment(context, param) {
// 通过commit("mutation名",载荷)触发Mutation,对state或getter中的数据进行操作
context.commit("Add",param);
}
}
// 准备mutations——用于操作数据
const mutations = {
Add(state,param) { // 第一个参数为state对象
state.age += param;
}
}
// state——用于存储公共数据
const state = {
age: 20
}
运行结果:
mapActions()
同理,通过使用Vuex定义的工具函数mapActions(),方法中会调用dispatch方法去联系Actions
// 导入辅助函数mapActions
import { mapActions } from "vuex";
export default {
name: "Info",
data() {
return {
n: 1,
};
},
methods: {
// handler() {
// this.$store.dispatch("increment", this.n);
// },
...mapActions({
handler: "increment",
}),
},
};
4.Mutation
使用它来对state或getter中的数据进行操作,从而对页面进行实时更新
- 组件可以通过dispatch触发Action,再在Action中通过commit触发Mutation,进而对state或getter中的数据进行操作
- 组件也可以直接通过commit触发Mutation,进而对state或getter中的数据进行操作
第一条线上文已经验证过了,现在验证第二条线
举个栗子:
// 组件Info
export default {
name: "Info",
data() {
return {
n: 1,
};
},
methods: {
// 按钮的点击事件handler,通过commit触发Mutation,对state或getters中数据进行操作
handler() {
this.$store.commit("Add", this.n);
},
},
};
// 准备mutations——用于操作数据
const mutations = {
Add(state,param) { // 第一个参数为state对象
state.age += param;
}
}
// 准备state——用于存储数据
const state = {
age: 20
}
运行结果:同上↑
同理,通过使用Vuex定义的工具函数mapMutations(),方法中会调用commit方法去联系mutations
import { mapMutations } from "vuex";
export default {
name: "Info",
data() {
return {
n: 1,
};
},
methods: {
// handler() {
// this.$store.commit("Add", this.n);
// },
...mapMutations({
handler: "Add",
}),
},
};
四、Vuex组件间通信
举个栗子:
组件一:Count.vue负责求和
组件二:Person.vue添加人物信息
需求:Count组件动态变更统计人物总数,Person组件动态变更求和信息
Count.vue
<template>
<div>
<h2>当前求和为:{{ sum }}</h2>
<h3>当前求和放大十倍为:{{ bigNum }}</h3>
<h3 style="color: red">下方组件的总人数为:{{ personList.length }}</h3>
<button @click="increment(n)">+</button>
<button @click="decrement(n)">-</button>
<button @click="incrementWait(n)">等500ms加</button>
</div>
</template>
<script>
// 引入vuex辅助函数
import { mapState, mapGetters, mapMutations, mapActions } from "vuex";
export default {
name: "Count",
data() {
return {
n: 1,
};
},
computed: {
...mapState({ // 借助mapState从state中读取数据
sum: "sum",
personList: "personList", // 获取Person组件中的数据
}),
...mapGetters(["bigNum"]), // 借助mapGetters从getters中读取数据
},
methods: {
...mapActions({
incrementWait: "incrementWait", // 借助mapActions生成对应方法,方法中会调用dispatch方法去联系Actions
}),
...mapMutations({ // 借助mapMutations生成对应方法,方法中会调用commit方法去联系mutations
increment: "Increment",
decrement: "Decrement",
}),
},
};
</script>
Person.vue
<template>
<div>
<h2>Person List</h2>
<h3 style="color: red">上方组件的求和为:{{ sum }}</h3>
<input type="text" placeholder="请输入人员信息" v-model="name" />
<button @click="AddPerson">添加</button>
<ul>
<li v-for="p in personList" :key="p.id">{{ p.name }}</li>
</ul>
</div>
</template>
<script>
import { nanoid } from "nanoid";
import { mapState } from "vuex";
export default {
name: "Person",
data() {
return {
name: "",
};
},
computed: {
...mapState({
personList: "personList",
sum: "sum", // 获取Count组件中的数据
}),
},
methods: {
AddPerson() {
const personObj = { id: nanoid(), name: this.name };
this.$store.commit("ADD_PERSON", personObj); // 使用原生方法触发Mutation
this.name = "";
},
},
};
</script>
index.js
// 该文件用于创建Vuex中最为核心的store
// 引入Vue
import Vue from 'vue';
// 引入Vuex
import Vuex from 'vuex';
// 应用Vuex插件
Vue.use(Vuex);
// 准备actions——用于响应组件中的动作
const actions = {
incrementWait(context,value) {
setTimeout(() => {
context.commit('Increment',value);
},500)
}
}
// 准备mutations——用于操作数据
const mutations = {
Increment(state,value) {
state.sum += value;
},
Decrement(state,value) {
state.sum -= value;
},
ADD_PERSON(state,value) {
state.personList.unshift(value);
}
}
// 准备state——用于存储公共数据
const state = {
sum: 9,
personList:[
{id:'001',name:'张三'},
{id:'002',name:'李四'}
]
}
// getters——用于将state中的数据进行加工
const getters = {
bigNum(state) {
return state.sum * 10
}
}
Vue.use(Vuex); // Vue中使用Vuex插件
// 创建并导出store
export default new Vuex.Store({
actions,
mutations,
state,
getters
});
运行结果:
可通过对该例进行阅读从而总结前文
总结
结合官方文档给的Vuex图示:对以上内容进行进一步总结:
总结不全,日后补充!有误望批评指正。