Vuex的学习笔记

对应的参考学习视频

👉https://www.bilibili.com/video/BV1Zy4y1K7SH?p=105

官网的原理图

https://vuex.vuejs.org/vuex.png

一、安装vuex

1. 2022年vuex的版本问题

在2022年,vue3成为默认版本,所以要指定vuex的安装版本来适配Vue2,所以安装vuex的命令如下
npm install vuex@3

2. 在项目src目录下新建store文件夹并新建index.js文件

注 : 如果使用vue-cli生成该项目时选用了vuex,那么vue-cli会自动帮你生成这些东西

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//创建vuex的核心Store

//引入
import Vuex from 'vuex'
import Vue from 'vue'

const actions = {}

const mutations = {}

const state = {}

Vue.use(Vuex)


//创建store,并暴露
export default new Vuex.Store({
actions,
mutations,
state,
})

3. 在store/index.js文件中使用Vue.use()的原因

如果你在main.js文件中使用Vue.use(Vuex),会报如下的错误:

❌ Uncaught Error: [vuex] must call Vue.use(Vuex) before creating a store instance.

这是因为, js总是先导入所有的import模块之后,再执行其他代码,所以根据上面错误的提示,需要先在store/index.js文件中,先将Vue.use(Vuex),然后再导出一个store实例

4. main.js里面的内容

只需要引入创建的store实例即可

1
import store from './store'

二、使用Vuex的基本流程

1. 将原本写在data中的数据写在state对象中

1
2
3
4
5
// store/index.js

const state = {
sum:0 //sum是公共的数据,代表数字总和
}

2. 在组件的方法中,调用dispatch并传递数据

1
2
3
4
5
6
7
//xxx.vue

methods:{
increment(){
this.$store.dispatch('jia',this.n) //jia是定义在actions对象中的方法,this.n是我们想要传递的数据
}
}

3. 在actions对象中调用commit并传递数据

1
2
3
4
5
6
7
8
// store/index.js

const actions = {
jia(context,value){
// console.log('jia',context,value)
context.commit('JIA',value) //JIA是我们定义在mutations中的方法,value就是this.n
}
}

4. 在mutations对象中处理state中的数据

1
2
3
4
5
6
// store/index.js

const mutations = {
JIA(state,value){ //mutations的方法名,全部大写. value == this.n
this.sum += value
}

注 : mutations对象中的方法名,最好全部大写,以示和actions的进行区分

5. 组件模版将处理好的state里的数据渲染

1
2
3
<div>
<h1>当前求和为:{{$store.state.sum}}</h1>
</div>

注 : 在模版中,无须加this,在script中的都要加this

各个对象的介绍

  • actions : 主要负责实现一些逻辑,比如请求数据,如果没有逻辑,则能跳过action ; 类似于后端service层
  • mulations : 主要是对数据进行底层的操作,相当于后端的dao层
  • state : 存放数据的对象,相当于后端的数据库
  • vue component : 提供给用户操作的视图,相当于前端页面和controller

如果对数据的操作没有什么逻辑,那么可以跳过actions对象,直接通过this.$store.commit方法调用mulations对象里面的底层操作方法

1
2
3
4
5
6
7
//  xxx.vue

methods:{
increment(){
this.$store.commit('JIA',this.n)
}
}

store对象的getters配置项(非必需配置项)

getters跟state的关系,类似于vue实例的data和computed的关系,一个是原始数据,一个是将原始数据经过运算得到的结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// store/index.js

const getters = { //定义getters
bigSum(){ //定义一个bigSum,返回的数据是num乘100
return state.num * 100
}
}

export default new Vuex.Store({
actions,
mutations,
state,
getters //配置使用getters
})
1
2
3
4
5
<div>
<h1>
当前求和的结果放大一百倍后为:{{$store.getters.bigSum}}
</h1>
</div>

三、进阶用法

1. mapState和mapGetters

存放在state中的数据,如果在组件模版中想要使用,每个数据都需要写上重复的 $store.state,于是乎,我们可以把对应的数据写成计算属性:

1
2
3
4
5
6
7
8
computed:{
sum(){
return this.$store.state.sum;
},
school(){
return this.$store.state.school;
}
}

如果数据一旦很多,那么就需要写很多的计算属性,十分麻烦

vuex中提供了自动生成这些计算属性的方法,就是mapState和mapGetters

🧧使用方法:

  • 首先引入mapState,mapGetters

    1
    import {mapState,mapGetters} from 'vuex'
  • 然后通过两种写法可以生成计算属性

    1. 对象写法(方法名和数据名不同)

      1
      mapState({zonghe:'sum'})  //key是方法名,value是数据名
    2. 数组写法(方法名和数据名相同)

      1
      mapState(['sum','school','age'])  //生成的方法名和数据名称是相同的
  • 将生成的方法添加到computed中

    1
    2
    3
    4
    computed:{
    ...mapState({sum:'sum'}),
    ...mapState(['school'])
    },

    ❗ 注:…是ES6中的语法,可以将A对象中的所有属性,全部添加到B对象中,因为mapState和mapGetters返回的是一个含有生成方法的对象

2.mapActions和mapMutations

mapActions,mapMulations和mapState,mapGetters类似,唯一就是参数的问题

🧧使用方法:

  • 首先引入

    1
    import {mapActions,mapMutations} from 'vuex'
  • 然后添加,这里同样有数组和对象两种写法,就不演示了

    1
    2
    3
    methods:{
    ...mapActions({increment:'jia'})
    }
  • ❗ 使用的时候要注意,需要在调用生成的方法的时候传入你得参数

    1
    <button @click="increment(arg)">+</button> //不加参数那么,就会自动传入event事件当参数

🚩3. 通过vuex实现组件间的数据共享

🧧实现组件共享数据只需要通过this.$store.state或者用mapXXX获取数据即可在自己得组件中使用公共state里的数据

🚩4. vuex的模块化和命名空间

目的:让代码更好维护,让多种数据分类更加明确

注:也可以不开启命名空间,同样可以通过模块化的方式对store进行分不同的文件管理

(1). 首先修改 store/index.js,创建两个新的对象,里面分别是对应的state、mutations、actions、getters,✨甚至可以创建单独的文件分别export,再在index中import进来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
const countAbout={
namespaced:true, //开启命名空间,重要!
state:{
x:1,
},
mutations:{...},
actions:{...},
getters:{
bigSum(state){
return state.sum * 10
}
}
}


const personAbout={
namespaced:true,
state:{...},
mutations:{...},
actions:{...}
}

const store = new Vuex.Store({
modules:{ //声明模块
countAbout,
persounAbout
}
})

(2)开启命名空间后,组件读取state数据

1
2
3
4
//方式1:自己读取
this.$store.state.personAbout.list
//方式2:借助mapState读取
...mapState('countAbout',['sum','school','subject']) //第一个参数就是对应的模块名字

(3)开启命名空间后,组件读取getters中的数据

1
2
3
4
//方式1:自己直接读取
this.$store.getters['personAbout/firstName'] //[]可以根据属性名,读取属性值,js基本功
//方式2:借助mapGetters读取
...mapGetters['coutnAbout',['bigSum']] //第一个参数也是对应的属性名字

(4)开启命名空间后,组件中调用dispatch

1
2
3
4
//方式1:自己直接dispathc
this.$store.dispatch('personAbout/addPersonWang',person) //第一个参数是模块中的actions中的方法
//方式2:借助mapActions
...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})

(5)开启命名空间后,组件中调用commit

1
2
3
4
//方式1:自己直接commit
this.$store.commit('personAbout/ADD_PERSON',person)
//方式2:借助mapMutations
...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'})

Vuex的学习笔记
http://blog.jingxiang.ltd/2023/03/30/Vuex的学习笔记/
作者
yemangran
发布于
2023年3月30日
许可协议