概念:专门在Vue中实现集中式状态(数据)管理的一个Vue插件,对Vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间的通信。
Github地址:Vuex
在组件中使用$store.dispatch('对应的action回调名')
触发
vue2要用vuex3版本,vue3要用vuex4版本
1.安装Vuex包
npm i vue@3
2.在main.js中引入Vuex
import store from './store/index.js'
new Vue({
store,
render: (h) => h(App),
}).$mount('#app')
3.在src中创建store文件夹,创建index.js,在index.js配置
// 该文件用于创建Vuex中的最为核心的store
import Vue from 'vue'
// 引入Vuex
import Vuex from 'vuex'
// 应用Vuex插件
Vue.use(Vuex)
// 准备actions---用于响应组件中的动作
const actions = {}
// 准备mutations---用于操作数据(state)
const mutations = {}
// 准备state---用于存储数据
const state = {}
// 创建并暴露store
export default new Vuex.Store({
actions,
mutations,
state,
})
$store.state.sum
$store.dispatch('action中的方法名', 数据)
或 $store.commit('mutation中的方法名', 数据)
actions
,即不写dispatch
,直接写commit
Count.vue
<template>
<div>
<h1>当前求和为:{{ $store.state.sum }}</h1>
<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 {
// eslint-disable-next-line vue/multi-word-component-names
name: 'Count',
data() {
return {
n: 1, //用户选择的数字
}
},
methods: {
increment() {
this.$store.commit('JIA', this.n)
},
decrement() {
this.$store.commit('JIAN', this.n)
},
incrementOdd() {
if (this.$store.state.sum % 2) {
this.$store.dispatch('jiaOdd', this.n)
}
},
incrementWait() {
setTimeout(() => {
this.$store.dispatch('jiaWait', this.n)
}, 500)
},
},
}
</script>
<style lang="css">
button {
margin-left: 8px;
}
</style>
store/index.js
// 该文件用于创建Vuex中的最为核心的store
import Vue from 'vue'
// 引入Vuex
import Vuex from 'vuex'
// 应用Vuex插件
Vue.use(Vuex)
// 准备actions---用于响应组件中的动作
const actions = {
// jia(context, value) {
// console.log('actions中的jia被调用了')
// context.commit('JIA', value)
// },
// jian(context, value) {
// console.log('actions中的jian被调用了')
// context.commit('JIAN', value)
// },
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---用于操作数据(state)
const mutations = {
JIA(state, value) {
console.log('mutations中的JIA被调用了')
state.sum += value
},
JIAN(state, value) {
console.log('mutations中的JIAN被调用了')
state.sum -= value
},
}
// 准备state---用于存储数据
const state = {
sum: 0, //当前的和
}
// 创建并暴露store
export default new Vuex.Store({
actions,
mutations,
state,
})
概念:当state中的数据需要经过加工后再使用时,可以使用getters加工。
在store/index.js中配置
const getters = {
xxx(state){
return state.数据名
}
}
//创建并暴露store
export default new Vuex.Store({
...
getters
})
$store.getters.xxx
以上面求和案例为例说明
computed: {
//借助mapState生成计算属性,sum、school、subject(对象写法)
...mapState({sum:'sum',school:'school',subject:'subject'}),
//借助mapState生成计算属性,sum、school、subject(数组写法)
...mapState(['sum','school','subject']),
}
computed: {
//借助mapGetters生成计算属性,bigSum(对象写法)
...mapGetters({bigSum:'bigSum'}),
//借助mapGetters生成计算属性,bigSum(数组写法)
...mapGetters(['bigSum']),
}
$store.dispatch(xxx)
的函数methods: {
//借助mapActions生成,incrementOdd、incrementWait(对象写法)
...mapActions({incrementOdd:'jiaOdd',increment:'jiaWait'})
//借助mapActions生成,incrementOdd、incrementWait(数组写法)
...mapActions(['jiaOdd','jiaWait'])
}
$store.commit(xxx)
的函数methods: {
//借助mapMutations生成,incrementOdd、incrementWait(对象写法)
...mapMutations({increment:'JIA',decrement:'JIAN'})
//借助mapMutations生成,JIA、JIAN(数组写法)
...mapMutations(['JIA','JIAN'])
}
注意:mapActions与mapMutations使用时,若需要传递参数需要:在模板中绑定事件时传递好参数,否则参数是事件对象。
Count.vue
<template>
<div>
<h1>当前求和为:{{ sum }}</h1>
<h3>当前求和放大10倍为:{{ bigSum }}</h3>
<h3>我在{{ school }},学习{{ subject }}</h3>
<select v-model.number="n">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button @click="increment(n)">+</button>
<button @click="decrement(n)">-</button>
<button @click="jiaOdd(n)">当前求和为奇数再加</button>
<button @click="jiaWait(n)">等一等再加</button>
</div>
</template>
<script>
import { mapState, mapGetters, mapMutations } from 'vuex'
export default {
// eslint-disable-next-line vue/multi-word-component-names
name: 'Count',
data() {
return {
n: 1, //用户选择的数字
}
},
computed: {
// 程序员自己写的计算属性
/* sum() {
return this.$store.state.sum
},
school() {
return this.$store.state.school
},
subject() {
return this.$store.state.subject
},
bigSum() {
return this.$store.getters.bigSum
}, */
// 借助mapState生成计算属性,从state中读取数据(对象写法)
// ...mapState({ sum: 'sum', school: 'school', subject: 'subject' }),
//借助mapState生成计算属性,从state中读取数据(数组写法)
...mapState(['sum', 'school', 'subject']),
/* ------------------------------------ */
//借助mapGetters生成计算属性,从getters中读取数据(对象写法)
// ...mapGetters({ bigSum: 'bigSum' }),
//借助mapGetters生成计算属性,从getters中读取数据(数组写法)
...mapGetters(['bigSum']),
},
methods: {
// 程序员自己写的方法
/* increment() {
this.$store.commit('JIA', this.n)
},
decrement() {
this.$store.commit('JIAN', this.n)
}, */
//借助mapMutations生成,incrementOdd、incrementWait(对象写法)
...mapMutations({ increment: 'JIA', decrement: 'JIAN' }),
//借助mapMutations生成,JIA、JIAN(数组写法)
// ...mapMutations(['JIA', 'JIAN']),
/* ------------------------------- */
// 程序员自己写的方法
/* incrementOdd() {
if (this.$store.state.sum % 2) {
this.$store.dispatch('jiaOdd', this.n)
}
},
incrementWait() {
setTimeout(() => {
this.$store.dispatch('jiaWait', this.n)
}, 500)
}, */
//借助mapMutations生成,incrementOdd、incrementWait(对象写法)
// ...mapMutations({ increment: 'JIA', decrement: 'JIAN' }),
//借助mapMutations生成,JIA、JIAN(数组写法)
...mapMutations(['jiaOdd', 'jiaWait']),
},
}
</script>
<style lang="css">
button {
margin-left: 8px;
}
</style>
store/index.js
// 该文件用于创建Vuex中的最为核心的store
import Vue from 'vue'
// 引入Vuex
import Vuex from 'vuex'
// 应用Vuex插件
Vue.use(Vuex)
// 准备actions---用于响应组件中的动作
const actions = {
// jia(context, value) {
// console.log('actions中的jia被调用了')
// context.commit('JIA', value)
// },
// jian(context, value) {
// console.log('actions中的jian被调用了')
// context.commit('JIAN', value)
// },
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---用于操作数据(state)
const mutations = {
JIA(state, value) {
console.log('mutations中的JIA被调用了')
state.sum += value
},
JIAN(state, value) {
console.log('mutations中的JIAN被调用了')
state.sum -= value
},
jiaOdd(state, value) {
console.log('mutations中的jiaOdd被调用了')
if (this.state.sum % 2) {
state.sum += value
}
},
jiaWait(state, value) {
console.log('mutations中的jiaWait被调用了')
setTimeout(() => {
state.sum += value
}, 500)
},
}
// 准备state---用于存储数据
const state = {
sum: 0, //当前的和
school: 'b站',
subject: '前端',
}
// 准备getters---用于将state中的数据进行加工
const getters = {
bigSum(state) {
return state.sum * 10
},
}
// 创建并暴露store
export default new Vuex.Store({
actions,
mutations,
state,
getters,
})
Count.vue
<template>
<div>
<h1>当前求和为:{{ sum }}</h1>
<h3>当前求和放大10倍为:{{ bigSum }}</h3>
<h3>我在{{ school }},学习{{ subject }}</h3>
<h3 style="color: red">Person组件的总人数:{{ personList.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="increment(n)">+</button>
<button @click="decrement(n)">-</button>
<button @click="jiaOdd(n)">当前求和为奇数再加</button>
<button @click="jiaWait(n)">等一等再加</button>
</div>
</template>
<script>
import { mapState, mapGetters, mapActions, mapMutations } from 'vuex'
export default {
// eslint-disable-next-line vue/multi-word-component-names
name: 'Count',
data() {
return {
n: 1, //用户选择的数字
}
},
computed: {
//借助mapState生成计算属性,从state中读取数据(数组写法)
...mapState('countAbout', ['sum', 'school', 'subject']),
...mapState('personAbout', ['personList']),
//借助mapGetters生成计算属性,从getters中读取数据(数组写法)
...mapGetters('countAbout', ['bigSum']),
},
methods: {
//借助mapMutations生成,incrementOdd、incrementWait(对象写法)
...mapMutations('countAbout', { increment: 'JIA', decrement: 'JIAN' }),
//借助mapActions生成,incrementOdd、incrementWait(数组写法)
...mapActions('countAbout', ['jiaOdd', 'jiaWait']),
},
}
</script>
<style lang="css">
button {
margin-left: 8px;
}
</style>
Person.vue
<template>
<div>
<h1>人员列表</h1>
<h3 style="color: red">Count组件求和为:{{ sum }}</h3>
<h3>列表中第一个人的名字是:{{ firstPersonName }}</h3>
<input type="text" placeholder="请输入名字" v-model="name" />
<button @click="add">添加</button>
<button @click="addWang">添加一个姓王的人</button>
<button @click="addPersonServer">添加一个人,名字随机</button>
<ul>
<li v-for="p in personList" :key="p.id">{{ p.name }}</li>
</ul>
</div>
</template>
<script>
import { nanoid } from 'nanoid'
export default {
// eslint-disable-next-line vue/multi-word-component-names
name: 'Person',
data() {
return {
name: '',
}
},
computed: {
personList() {
return this.$store.state.personAbout.personList
},
sum() {
return this.$store.state.countAbout.sum
},
firstPersonName() {
return this.$store.getters['personAbout/firstPersonName']
},
},
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>
store/index.js
// 该文件用于创建Vuex中的最为核心的store
import Vue from 'vue'
// 引入Vuex
import Vuex from 'vuex'
import countOptions from './count.js'
import personOptions from './person.js'
// 应用Vuex插件
Vue.use(Vuex)
// 创建并暴露store
export default new Vuex.Store({
modules: {
countAbout: countOptions,
personAbout: 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: 'b站',
subject: '前端',
},
getters: {
bigSum(state) {
return state.sum * 10
},
},
}
store/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) {
// 这个是一个随机生成一句语录的API端口
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
},
},
}