一. 介绍
1. 概念
Vuex
是一个专为Vue.js
应用程序开发的状态管理模式(状态管理工具).采用集中式存储管理应用的所有组件的状态,此昂已响应的规则保证状态以一种可预测的方式发生变化.
状态管理模式、集中式存储管理: 将把需要多个组件共享的变量存储到一个对象中,再将此对象放在顶层的
Vue
实例中,实现具有响应式的组件内容共享
通常使用Vuex
进行信息共享的内容有: token
, 用户信息等
二. 使用
1. 注册
vue2
对应vuex3.x
// vuex的index.js
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
// 属性名是固定的,不可修改
// state存储需要共享的变量或状态
state: {
// 定义共享变量或属性
name: 'xiaolin'
},
mutations: {
},
actions: {
},
modules: {
}
})
export default store
// main.js
import Vue from 'vue'
import store from './store'
new Vue(
el: '#app',
store,
// ...
)
vue3
对应vuex4.x
// vuex的index.js
import {createStore} from 'vuex'
const store = createStore({
// 见官方修改state中内容图解
// component ----Dispatch----> Actions ----Commit----> Mutations ----Mutate----> State
// 也支持直接通过Mutations修改,跳过Actions步骤
// 属性名是固定的,不可修改
// state存储需要共享的变量或状态
state: {
// 定义共享变量或属性
name: 'xiaolin'
},
mutations: {
// 定义修改state的内容的函数
},
actions: {
// 定义行为,通常是在修改state中的内容的同时有异步操作时使用
// 不建议在Mutation进行异步操作
},
modules: {
}
})
export default store
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
createApp(App).use(store).use(router).mount('#app')
注意
:vue3
的实例创建方式发生了变化,需要注意vue
的版本和组件
版本,在vue3
中不支持Vue.vue(plugin)
,所以需要使用有createXxx
函数的版本插件
2. 基本使用
- 定义共享内容: 在注册
vuex
插件时,即可同时定义共享内容 - 获取: 在任意插件中都可通过
this.$store.state.xxx
获取共享的内容 - 修改: 通过
mutations
中定义函数修改state
中定义的内容
mutations: {
// mutation中定义的函数,参数会传定义的store中的state对象
increment(state) {
state.counter ++;
}
}
调用方式:
this.$store.commit('increment')
3. Vuex
的核心概念
State
: 单一状态定义状态,可以直接调用查看,不建议直接修改Getters
: 类似计算属性,可以对State
中定义的内容进行处理后返回
// 定义
getters: {
// 基本使用
powerCounter: state => {
return state.counter * state.counter;
},
// getters中调用定义的getters
thirdPowerCounter: (state, getters) => {
return getters.powerCounter * state.counter
},
// getters中的参数是固定的,所以需要使用接受的参数时,可以返回一个函数,此时调用getters实际就是调用定义的函数,接收到的参数就是定义的函数的参数
counterMoreNumber: (state, getters) => {
return function(number) {
return state.counter > number;
}
}
}
// 使用
// getters是当做属性来使用的,所以不需要"()"
this.$store.getters.powerCounter
// 当getters返回的是一个函数时,调用该getters就是调用该函数,需要添加"()","()"中的参数就是返回的函数中传入的参数
// 如下相当于 return state.counter > 3
this.$store.getters.counterMoreNumber(3);
Mutation
: 修改State
中定义的状态(唯一方式),通常要求必须是同步函数
Mutation
主要包括两部分:mutations: { increment(state) { state.counter ++ ;} }
- 字符串的事件类型(
type
),如上述的increment
,通常会认为是函数名称;在通过mutation
更新state
时,commit
函数的参数就是事件类型- 一个回调函数(
handler
),该回调函数的第一个参数就是state
,第二个参数是接受调用时传入的参数,如上述事件类型后面跟的函数,通常是函数体
mutation
的定义和调用
- 参数被称为
mutation
的载荷(payload)- 如果有多个参数,通常使用对象行使传递
提交方式
普通提交方式
mutations: {
addStudent(state, payload) {
// 普工提交方式的payload得到的就是参数对象
state.students.push(payload);
}
}
let student = {id: 1, name: 'xiaolin', age: 18}
// 此处调用时传入的student参数通常称为payload(负载)
this.$store.commit('assStudent', student)
包含type
属性的对象提交方式
mutations: {
addStudent(state, payload) {
// 使用对象方式提交时,payload实际是整个mutation调用时的对象
state.students.push(payload.stadent);
}
}
let student = {id: 1, name: 'xiaolin', age: 18}
// 使用一下方式提交时,payload对象实际是整个参数对象{type: 'addStudent', student: {id: 1, name: 'xiaolin', age: 18}}
this.$store.commit({
type: 'addStudent',
student
})
响应规则
store
中的state
是响应式的,但必须遵守对应的规则
提前在
store
中初始化好所需的属性当给
state
中的对象添加或删除属性时, 使用如下方式:-方式一:使用
Vue.set(targetObj, 'key', value);Vue.delete(targetObj, 'key')
-方式二: 用新对象给旧对象重新赋值
注意: 在使用vuex4.x
时,对应的vue
版本生成Vue
实例(即app
)的方式改为使用createApp
方法生成,而不是new
,vuex
也使用createStore
方法生成store
,所以Vue.set
方法无法获取,在4.x
版本中的官方文档中也将Mutation
需遵守Vue
的响应规则 这一节内容删除;作为代替,可以直接给state
中的对象添加内容,如mutations: { updateInfo(state) { state.info['age'] = 18 } }
mutations: {
setField(state, payload) {
Vue.set(state, payload.key, payload.student)
}
}
this.$store.commit({
type: 'setField',
key: 'info',
student
})
Action
: 处理(异步)操作
Action
类似Mutation
,但允许异步操作
一般使用方式
updateStuInfo(context, payload) {
// 此处的context上下文就是store
setTimeout(() => {
context.commit('updateInfo')
}, 1000)
}
let payload = {// ...}
this.$store.dispatch('updateStuInfo', payload)
返回提示信息的方式
updateStuInfo(context, payload) {
return new Promise((resolve, reject) => {
setTimeout(() => {
context.commit('updateInfo')
resolve()
}, 1000)
})
}
let payload = {// ...}
this.$store.dispatch('updateStuInfo', payload).then(() => {
// ...
})
Module
: 分模块,将store
中的内容分割成模块(Module
),每个模块拥有字节的state
,mutations
,actions
,getters
const user = {
namespaced: true,
state: {
name: 'xiaolin'
},
getters: {
// state 是当前模块的state
// getters 是当前模块的getters
// rootState 是根节点的state
getUserName(state, getters, rootState) {
return state.name + "好帅!"
}
},
mutations: {
userMutation(state, mutations, rootState) {
// ...
}
},
actions: {
userAction(state, actions, rootState) {
// ...
}
}
}
modules: {
user: user
}
使用
this.$store.state.user.name;
// getters, mutations, actions命名空间未定义时调用方式
this.$store.getters['getUserName']
this.$store.commit('userMutation')
this.$store.dispatch('userAction')
// getters, mutations, actions命名空间为true时调用方式
this.$store.getters['user/getUserName']
this.$store.commit('user/userMutation')
this.$store.dispatch('user/userAction')
三. 整体案例
定义
import { createStore } from 'vuex'
// 定义一个user模块
const user = {
// 命名空间设为true和不设为true是有区别的
// 主要是内容归属问题
// 当为true时,则表示内容属于当前子项
// 否则表示内容不区域无差别
namespaced: true,
state: () => ({
name: 'xiaolin',
}),
getters: {
// state 是当前模块的state
// getters 是当前模块的getters
// rootState 是根节点的state
// getters和rootState名称可以换
getUserName(state, getters, rootState) {
console.log("state:", state);
console.log("getters", getters);
console.log("rootState", rootState);
return state.name + "好帅!"
},
},
mutations: {
userMutation(state, payload) {
console.log("state", state);
console.log("payload", payload);
}
},
actions: {
// context对象
userAction(context) {
console.log("state", context.state);
console.log("commit", context.commit);
console.log("rootState", context.rootState);
}
}
}
export default createStore({
state: {
counter: 0,
info: {
name: 'xiaolin',
age: 18
}
},
getters: {
getInfo: state => {
return state.info
}
},
mutations: {
increment(state) {
state.counter++
},
updateInfo(state) {
state.info['id'] = 1
}
},
actions: {
infoAction(state) {
setTimeout(() => {
console.log("infoAction");
})
}
},
modules: {
user: user
}
})
调用
console.log("info", this.$store.state.info);
console.log("-------------");
console.log("user.name", this.$store.state.user.name);
console.log("-------------");
this.$store.commit('increment')
console.log("-------------");
console.log("counter", this.$store.state.counter);
this.$store.getters['user/getUserName'];
console.log("-------------");
this.$store.commit('user/userMutation', 'payload);
console.log("-------------");
this.$store.dispatch('user/userAction');
结果
子模块的Action
中的context
参数的内容:
日 期 : 2021 − 12 − 01 \color{#00FF00}{日期:2021-12-01} 日期:2021−12−01