Vuex
提示:
本博客为个人学习中一些笔记整理,如有错误欢迎指正。
部分内容搬运前辈们总结的知识结晶,部分内容为自己在学习中的debug
  ——md空格方式之一
本文章适用于Vue2,Vue3可能对于某些内容进行更新
Vuex可以简单理解为Vue项目的状态管理库,采用集中式存储管理所有组件的状态。
Vuex官方教程
安装并使用
terminal安装:npm install vuex@next --save
默认安装最新版本,但是对于vue2而言,vuex应该使用3版本;对于vue3而言,vuex应该使用4版本,如果我们项目是vue2,此时就不能用上面的默认命令下载,而是安装特定版本
terminal:npm install vuex@3
安装完之后需要使用插件,需要执行Vue.use(),不过我们使用vuex需要使用store仓库进行管理
1.在项目中创建了store文件夹(在src目录下)用来表示Vuex,在里面实现了模块划分(后面会介绍module概念),并且用store.js作为export注册在项目main.js中,以便函数调用
2.在store.js中进行使用vuex并且创建vuex实例
store.js
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
states,
mutations,
actions,
modules{
x // x为自定义模块
}
})
3.在/src/main.js中进行指定store,这样vm(Vue实例对象)和vc(VueComponent实例对象)全都可以使用$store
main.js
import store from './store/store'
const vm = new Vue({
router,
//在这里指定store属性
store,
render: h => h(App)
}).$mount('#app')
Vuex由几大核心内容组成,分别为state、getter、mutation、action、module,下面将一一介绍。
state
Vuex使用单一状态树(一个Vue项目只有一个store)。个人理解Vuex为前端项目的“数据库”,虽然能够记录所有组件的状态,但并不推荐,只对组件通信中常用状态进行记录和管理即可。
创建moduleA.js,并定义一些state状态
moduleA.js
const moduleA = {
state:{
typeA: 'A',
numOfA: 1,
A:{
isLetter: true,
nextLetter: 'B'
}
},
getters:{...},
mutations:{...},
actions:{...},
}
getter
getter可以理解为状态的获取器,可以返回状态简单运算后的结果
getter的声明:如获取typeA等状态,此外getter支持其它函数的调用
moduleA.js
const moduleA = {
state:{...},
getters:{
TypeA: state =>{
return state.typeA
},
NumOfA: state =>{
return ++state.numOfA
},
IsLetter: state =>{
return state.A.isLetter
}
},
mutations:{...},
actions:{...}
}
如何调用getter:通过computed计算属性调用
index.vue
<script>
import {mapGetters} from 'vuex'
export default {
name:'home',
data(){
return{...}
},
computed:{
//此时我获取的是getter返回的结果(可能在原状态的基础上做了一些改变)
...mapGetters('moduleA',[
'TypeA',
'IsLetter'
]),
//此时获取的是状态
...mapStatus('moduleA',[
'typeA',
'numOfA'
])
},
methods:{
//获取仓库中A的类型并打印
JudgeA(){
console.log(this.IsLetter)
}
}
}
</script>
mutation
mutation负责修改state,即状态的修改器。mutation有规定的语法格式:每个mutation都包含一个事件类型(type)和一个回调函数(handler)
个人理解事件类型即为mutation的名字,回调函数为具体函数代码
修改numA的值
moduleA.js
const moduleA = {
state:{...},
getters:{...},
mutations:{
setNumOfA(state,data){
state.numA += data
},
setTypeA(state){
state.typeA = 'B'
}
},
actions:{...}
}
官方定义状态修改为事件注册,而非所谓的调用mutation(个人感觉只是说法问题)
为什么要进行store声明
下面是事件注册示例,首先需要先进行this.$store的声明(在本人项目中是这样实现的)
在具体的vue文件中进行状态修改(mutation)
index.vue
methods:{
//修改仓库中numA的状态,函数名是自定义的
AddNumA(data){
//commit里首先指定模块以及具体的mutation,参数为可选项
this.$store.commit('moduleA/setTypeA')
this.$store.commit('moduleA/setNumOfA',data)
}
}
action
mutations可以直接对状态进行修改,但是action不能,需要通过调用mutation来实现对状态的修改。但是如果仅仅是这样的话,似乎action有点多此一举了,存在的原因在于action可以进行异步操作,可以做一些复杂处理。
const moduleA = {
state:{...},
getters:{...},
mutations:{...},
actions:{
//当data为奇数时,才触发mutation
//context是上下文,可以简单地理解为this.$store
addOdd(context,data){
if (context.state.numOfA %2){
context.commit('setNumOfA',data)
}
}
}
调用action
methods:{
//修改仓库中numA的状态,函数名是自定义的
AddOddOfA(data){
//commit里首先指定模块以及具体的mutation,参数为可选项
this.$store.dispatch('moduleA/addOdd',2)
}
}
module
对于中大型项目而言,太多的状态如果堆积在一个JS文件中会特别混乱,因此Vuex支持将store划分为一个个module(模块),每个module拥有自己的state、getter、mutation以及action。
下图是一个项目中对store按模块进行划分的目录,下面以modules/Fate/FateConfStore.js为例
如果将store进行module划分,为了保证模块更高的封装性和复用性,引出了命名空间这一概念。
1.创建FateConfStore
FateConfStore.js
const FateConfStore = {
namespaced: true,
state:{...},
getters:{...},
mutations:{...},
actions:{...},
}
2.创建完模块后,需要先将其注册到store.js中
store.js
import Vue from 'vue'
import Vuex from 'vuex'
import FateConfStore from "@/store/modules/Fate/FateConfStore";
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
FateConfStore,
...
}
})
3.之后就可以对该模块正常访问了
比如:
//获取A的状态
computed:{
...mapGetters('FateConfStore',[
'getterA'
])
},
//修改A的数值
methods:{
addA(data){
this.$store.commit('FateConfStore/AddNumOfA',data)
}
}
浏览器扩展工具Vue.js devtools
当我们debug时,该工具可以很方便地查看Vuex仓库的状态
下面是浏览器应用商店的搜索结果
下面是debug的时候F12显示结果