一、介绍
1. 什么时候使用 Vuex
多组件共享同一数据时
2. 原理图
二、简单使用
1. 安装 vuex 插件
vue2 使用 vuex3
npm i vuex@3
vue3 使用 vuex4
npm o vuex@4
2. 将 Vuex 插件封装成 store 对象
src/store/index.js
:理论上可以随便命名
import Vue from 'vue'
import Vuex from 'vuex'
import axios from "axios";
Vue.use(Vuex)
const actions = {
showMsgByLength(context) {
if (context.state.msg.length >= 6) {
// 逻辑判断完成,交给 mutations 执行函数
context.commit('SHOW_MSG')
} else {
console.log('【actions 】', context.state.msg, 'msg长度小于6')
}
},
showMsgByLengthAndParams(context, value) {
if (context.state.msg.indexOf(value) !== -1) {
// dispatch 调用链
context.dispatch('showMsgByLength')
} else {
console.log('【actions 】', context.state.msg, `msg不包含参数"${
value}"`)
}
},
sendRequest(context) {
axios.get('https://v1.hitokoto.cn/').then(
request => {
context.commit('SHOW_ONE_DATA', request.data.hitokoto)
},
error => {
console.log(error.message)
}
)
}
}
const mutations = {
// 命名建议:大写
SHOW_MSG(store) {
console.log('【mutations】', store.msg)
},
SHOW_MSG_And_PARAMS(store, params) {
console.log('【mutations】', store.msg, `传递的参数为"${
params}"`)
},
SHOW_ONE_DATA(store, params) {
console.log('请求到的每日一句为:', params)
}
}
const state = {
msg: 'Hello, MyComponent',
}
const getters = {
getMsgLength(state) {
return state.msg.length
}
}
export default new Vuex.Store({
actions,
mutations,
state,
getters
})
3. 引入并绑定 store 对象
src/main.js
:将封装的 store 对象绑定到 vue 实例身上
import store from 'src/store/index.js'
new Vue({
el:'#app',
// 绑定
store,
render: h => h(App),
// 验证是否绑定成功
mounted() {
console.log(this)
},
})
4. 使用 store 对象
methods: {
// 直接通过 commit 执行函数【不传递参数】
showMsg() {
this.$store.commit('SHOW_MSG')
},
// 直接通过 commit 执行函数【传递参数】
showMsgAndParams() {
this.$store.commit('SHOW_MSG_And_PARAMS', '11')
},
// 通过 dispatch 进行逻辑判断之后再 commit 执行函数【不传递参数】
showMsgByLength() {
this.$store.dispatch('showMsgByLength')
},
// 通过 dispatch 进行逻辑判断之后再 commit 执行函数【传递参数】
showMsgByLengthAndParams() {
this.$store.dispatch('showMsgByLengthAndParams', '123456')
},
// 在 actions 发送请求
sendRequest() {
this.$store.dispatch('sendRequest')
}
},
computed:{
// 展示 getters 的作用
showGetters() {
return this.$store.getters.getMsgLengt
},
}
5. 细节说明
(1)上下文对象的说明
上下文对象里面封装了一些重要的数据
context = {
commit: function(){
},
dispatch: function(){
},
getters:{
},
state:{
},
......
}
dispatch:可以利用它实现 dispatch 调用链
showMsgByLengthAndParams(context, value) {
if (context.state.msg.indexOf(value) !== -1) {
// dispatch 调用链
context.dispatch('showMsgByLength')
} else {
console.log('【actions 】', context.state.msg, `msg不包含参数"${
value}"`)
}
}
state:数据,可以进行逻辑处理
commit:保证了动作的最终执行调用
showMsgByLength(context) {
if (context.state.msg.length >= 6) {
context.commit('SHOW_MSG')
} else {
console.log('【actions 】', context.state.msg, 'msg长度小于6')
}
}
getters:类似于计算属性,用于所有组件复用
getMsgLength(state) {
return state.msg.length
}
(2)在 actions 发送请求
sendRequest(context) {
axios.get('https://v1.hitokoto.cn/').then(
request => {
context.commit('SHOW_ONE_DATA', request.data.hitokoto)
},
error => {
console.log(error.message)
}
)
}
三、四个 mapXXX 的使用
上面完全足够使用了,但是 vue 还提供了简写
- mapState
- mapGetters
- mapActions
- mapMutations
借助 mapState 生成 computed,直接访问 state 数据
借助 mapGetters 生成 computed,直接访问 state 数据
computed: {
// 方法一:对象写法
...mapState({
sum:'sum',
school:'school',
subject:'xueke'
}),
// OR
// 方法二:数组写法,当 state 的数据名称与生成的计算属性名称相同时,可以使用数组简写
...mapState([
'sum',
'school'
]),
...mapState({
subject:'xueke'
}),
}
computed: {
// 方法一:对象写法
...mapGetters({
msgLength:'msgLength'
}),
// OR
// 方法二:数组写法
...mapGetters([
'msgLength'
]),
}
借助 mapActions 生成 methods,直接 dispatch 到 actions 里面进行逻辑判断
借助 mapMutations 生成 methods,直接 commit 到 mutations 里面进行处理
methods:{
// 方法一:对象写法
...mapActions({
showMsgByLength:'showMsgByLength',
showMsgByLengthAndParams:'showMsgByLengthAndParams'
})
// OR
// 方法二:数组写法
...mapActions([
'showMsgByLength',
'showMsgByLengthAndParams'
])
}
methods:{
// 方法一:对象写法
...mapMutations({
SHOW_MSG:'SHOW_MSG',
SHOW_MSG_And_PARAMS:'SHOW_MSG_And_PARAMS'
}),
// OR
// 方法二:数组写法
...mapMutations([
'SHOW_MSG',
'SHOW_MSG_And_PARAMS'
]),
}
需要注意的是:使用 mapActions 和 mapMutations 时,传递参数的位置在模板绑定事件时传递,如果不手动传递参数的话,默认传递一个事件对象作为参数
四、store 的模块化
1. store 的模块化
为每个模块的配置开启命名空间
const StudentAbout = {
// 开启命名空间
namespaced: true,
state: {
},
getters: {
},
actions: {
},
mutations: {
}
}
const PersonAbout = {
namespaced: true,
state: {
},
getters: {
},
actions: {
},
mutations: {
}
}
const store = new Vuex.Store({
modules: {
// key:value
// - key: 每个模块的命名空间
// - value:每个模块的配置
StudentAbout: 'StudentAbout',
PersonAbout: 'PersonAbout',
}
})
2. 模块化之后的使用
state
getters
// 方式一:直接读取
this.$store.state.StudentAbout.stuList
this.$store.state.PersonAbout.perList
// 方式二:借助 mapState 读取
...mapState('StudentAbout',['stuList']),
...mapState('StudentAbout',{
xueke: 'subject',
})
...mapState('PersonAbout',{
perList: 'perList',
})
// 方式一:直接读取
// this.$store.getters.PersonAbout/nameLength
// 本来是上面这样读取,但是因为有 "/",所以改成下面的格式读取
this.$store.getters['PersonAbout/nameLength']
// 方式二:借助 mapGetters 读取
...mapGetters('PersonAbout',['nameLength'])
...mapGetters('PersonAbout',{
nameLength: 'nameLength'
})
actions
mutations
// 方式一:直接 dispatch
this.$store.dispatch('PersonAbout/addPersonWang', person)
// 方式二:借助 mapActions:注意不要忘了参数的传递
...mapActions('PersonAbout',{
addPersonWang:'addPersonWang',
})
// 方式一:直接 commit
this.$store.commit('PersonAbout/ADD_PERSON', person)
// 方式二:借助 mapMutations
...mapMutations('PersonAbout',{
addPerson:'ADD_PERSON'
}),