目录
一、概念
什么是vuex:专门在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信
什么时候使用Vuex:
- 多个组件依赖于同一个状态
- 来自不同组件的行为需要变更同一状态
- 总的来说就是共享的情况下
二、使用步骤
第一步:安装vuex
npm i vuex
第二步:创建store文件夹,新建一个index.js文件 ,该文件用于创建vuex中最为核心的store
//引入vue
import Vue from 'vue'
// 引入Vuex
import Vuex from "vuex"
// 使用Vuex
Vue.use(Vuex)
//准备actions--用于响应式组件中的动作,业务逻辑写在这儿
const actions = {....}
//准备mutation--用于操作数据(state)只能是操作
const mutations = {....}
//准备state--用于存储数据
const state ={....}
//准备getters--用于将state中的数据进行加工
const getters = {....}
//创建并暴露store
export default new Vuex.Store({
actions,
mutations,
state,
getters
})
第三步:在入口函数中传入store配置项
import Vue from "vue";
import App from './App.vue'
// 引入store
import store from './store/index'
Vue.config.productionTip = false
//创建vue
new Vue({
el: '#app',
render: h => h(App),
store: store, //可以简写成store
})
组件中读取vuex中的数据:【多组件数据共享也是一样,通过下面的方法可以拿到数据】
$store.state.xx
$store.getters.xx
组件中修改vuex的数据:
方法一:$store.dispatch('action中的方法名',数据)
方法二:$store.commit('mutations中的方法名',数据) 注意:方法名需要大些
三、四个map方法的使用 ---------多组件共享数据
组件中导入:
import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
⚠️ 注意 :以下数组写法的条件是:当计算出来的属性和读取数据名是一样的,一个属性有两个用法
3.1、mapState 方法
作用:用于帮助我们映射state中的数据为计算属性
对象写法:
...mapState({he:'sum',xuexiao:'school',xueke:'subject'})
数组写法:
...mapState(['sum','school','subject'])
3.2、mapGetters 方法
作用:用于帮助我们映射getters中的数据为计算属性
对象写法:
...mapGetters({bigSum:'bigSum'})
数组写法:
...mapGetters(['bigSum'])
⚠️ 注意 :以下数组写法的条件是:当方法名和提交的方法名是一样的,一个方法有两个用法
3.3、mapMutations方法
作用:用于帮助我们生成与Mutations对话的方法,即写在$store.dispatch(xxx)的函数, 写在methods里面, 方法中会调用commit去联系mutations
对象写法:<button @click="increament(n)">+</button> 点击事件函数需要携带参数的哟
...mapMutations({ increament:'JIA',decreament:'JIAN'})
数组写法:
...mapMutations(['JIA','JIAN'])
3.4、mapActions方法
作用:用于帮助我们生成与actions对话的方法,即$store.dispatch(xxx)的函数,方法中会调用dispatch去联系actions
对象方法:
...mapActions({inceamentOdd:'jiaOdd',increamentWait:'Waitjia'})
数组写法:
...mapActions(['jiaOdd','Waitjia'])
四、模块化加命名空间
目的:让代码更加好维护,让多种数据分类更加明确
命名空间
引入命名空间解决不同模块内名称冲突的问题
在设置namespaced: true后的模块无论进行什么操作都会去查找自身模块中的方法,在commit提交product/setName事件,而导出时的setName事件正好变为product/setName这样完美的进行了事件在本模块的抛发并且不会影响其他模块
请看实例:
store/index.js
引入store文件下的 person.js 和count.js
并配置:modules:{
countAbout:countOption,
personAbout:personOption,
}
// 该文件用于创建vuex中最为核心的store
//引入vue
import Vue from 'vue'
// 引入Vuex
import Vuex from "vuex"
// 使用Vuex
Vue.use(Vuex)
import personOption from './person'
import countOption from './count'
//创建并暴露store
export default new Vuex.Store({
modules: {
countAbout: countOption,
personAbout: personOption,
}
})
store/person.js
关于人员相关的配置写到这个文件里面
const personOption = {
namespaced:true, //命名空间
actions: {....}
mutations : {....}
state : {....}
getters : {....}
}export default personOption
import axios from "axios";
import { nanoid } from "nanoid";
//人员管理相关的配置
const personOption = {
namespaced: true,
actions: {
addPersonWang(context, value) {
console.log(1);
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.massage)
}
)
}
},
mutations: {
ADD_PERSON(state, value) {
state.Person.unshift(value)
}
},
state: {
Person: [
{ id: '001', name: '张三' }
]
},
getters: {
firstName(state) {
return state.Person[0].name
}
}
}
export default personOption
store/count.js
关于求和相关的配置写到这个文件里面
const countOption = {
namespaced:true, //命名空间
actions: {....}
mutations : {....}
state : {....}
getters : {....}
}export default countOption
//求和相关的配置
const countOption = {
namespaced: true,
actions: {
jiaOdd(context, value) {
if (context.state.sum % 2) {
context.commit('JIA', value)
}
},
Waitjia(context, value) {
setTimeout(() => {
context.commit("JIA", value)
}, 500);
}
},
mutations: {
JIA(state, value) {
state.sum += value
},
JIAN(state, value) {
state.sum -= value
},
},
state: {
sum: 0, //当前求和
school: '尚硅谷',
subject: '计算机',
},
getters: {
bigSum(state) {
return state.sum * 10
}
}
}
export default countOption
Count.vue 组件:
用map提供的方法:
...mapState('countAbout',['sum','school','subject'])
开启命名空间后: 最终查找的是 /countAbout/sum
<template>
<div>
<h2>求和的结果为:{{ sum }}</h2>
<h4>求和的结果放大10倍:{{ bigSum }}</h4>
<h5>我在{{ school }},学习{{ subject }}</h5>
<h3 style="color: red">下方人数的总数为:{{ Person.length }}</h3>
<select v-model.number="n">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button @click="increament(n)">+</button>
<button @click="decrement(n)">-</button>
<button @click="increamentOdd(n)">当前求和为奇数再加</button>
<button @click="increamentWait(n)">等一等再加</button>
</div>
</template>
<script>
import { mapState, mapGetters, mapMutations, mapActions } from "vuex";
export default {
name: "Count",
data() {
return {
n: 1, //用户选择的数字
};
},
computed: {
...mapState("countAbout", ["sum", "school", "subject"]),
...mapState("personAbout", ["Person"]),
...mapGetters("countAbout", ["bigSum"]),
},
methods: {
...mapMutations("countAbout", { increament: "JIA", decrement: "JIAN" }),
...mapActions("countAbout", {
increamentOdd: "jiaOdd",
increamentWait: "Waitjia",
}),
},
}
</script>
Person.vue组件
自己写的计算属性:注意两者的区别
this.$store.state.personAbout.Person
this.$store.getters['personAbout/firstName']
自己写的方法
this.$store.commit("personAbout/ADD_PERSON", personObj);
<template>
<div>
<h3>人员列表</h3>
<h3>第一个人的名字为:{{ firstName }}</h3>
<input type="text" v-model="name" />
<button @click="add">添加</button>
<button @click="addWang">添加一个姓王的人</button>
<button @click="addPersonServer">随机添加一个人名</button>
<ul>
<li v-for="p in Person" :key="p.id">{{ p.name }}</li>
</ul>
<h3 style="color: red">上方组件的sum为:{{ sum }}</h3>
</div>
</template>
<script>
import { nanoid } from "nanoid";
export default {
name: "Person",
data() {
return {
name: "",
};
},
computed: {
Person() {
return this.$store.state.personAbout.Person;
},
sum() {
return this.$store.state.countAbout.sum;
},
firstName() {
return this.$store.getters["personAbout/firstName"];
},
},
methods: {
add() {
const personObj = { id: nanoid(), name: this.name };
this.$store.commit("personAbout/ADD_PERSON", personObj);
this.name = "";
},
addWang() {
const personObj = { id: nanoid(), name: this.name };
this.$store.dispatch("personAbout/addPersonWang", personObj);
this.name = "";
},
addPersonServer() {
//因为是随机添加的一个人名,所有不用带数据,是请求服务器得到的数据
this.$store.dispatch('personAbout/addPersonServer')
},
},
}
</script>