vuex 是什么

vuex 是vue集成的一个状态管理器,当多个组件都用到了同一个状态变量时,我们可以把那个状态变量交给vuex,这样,所有组件都可以直接从vuex 中获取对应的数据,免去了各个组件相互传参的繁琐过程,而且,vuex是响应式的,当里面的数据发生变化时,所有用到了这个数据的组件都会进行对应的更新

在父子组件中,状态传递通过父子组件传值即可,vuex主要用于各个兄弟组件或毫无关系的组件之间的状态管理。

安装与基本使用

  1. 使用 npm install vuex --save 安装

  2. 创建 store 文件夹,并建立index.js 文件 用于编写 vuex相关配置

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
import Vue from 'vue'
import Vuex from 'vuex'

// 1.安装插件
Vue.use(Vuex)

// 2.创建对象
const store = new Vuex.Store({
state:{ //用于定义状态
isLogin:false
},
mutations:{ // 用于更改状态

},
actions:{

},
getters:{

},
modules:{

}
})

// 3.导出对象
export default store

  1. 在main.js 中导入,并挂载
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store/index.js'


Vue.config.productionTip = false

new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>'
})

  1. 在组件中使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<template>
<div id="wapper">
<h2>当前的登录状态是 {{$store.state.isLogin}}</h2>
</div>
</template>

<script>
export default {
data() {
return {
};
},
};
</script>

<style scoped >
</style>

修改 vuex 中的状态

在配置文件中 配置 mutations 定义两个修改状态的方法

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
29
30
31
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)


const store = new Vuex.Store({
state:{
isLogin:false
},
mutations:{
clearLoginState(state){
state.isLogin = false
},
loginSuccess(state){
state.isLogin = true
}
},
actions:{

},
getters:{

},
modules:{

}
})

export default store

在组件中 调用mutations 即可

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
<template>
<div id="wapper">
<button @click="Sublogin">登录</button>
<button @click="Cenllogin">取消</button>
</div>
</template>

<script>
export default {
data() {
return {
};
},
methods:{
Sublogin(){
//传入 mutations 中定义的方法
this.$store.commit('loginSuccess')
},
Cenllogin(){
this.$store.commit('clearLoginState ')
}
}
};
</script>

<style scoped >
</style>

使用浏览器插件 vue devtools 来跟踪 vuex状态修改

在实际开发中,有可能有很多个组件都会修改 vuex中的状态,这时我们就需要一个工具来追踪每一次的修改,以便修改 vuex后出现bug时,快速定位

  1. 下载安装 vue devtools 插件,注意把插件中的 允许访问文件网址 选项打开

  1. 在 vue程序界面 打开控制台 可以使用该插件进行调试

  2. 可以追踪每一次状态的修改

vuex 五个核心配置

state

state 就是vuex 存放状态的地方,是vuex的核心

getters

getters 类似于 计算属性,用于对state中的数据进行一些计算

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
29
30
31
32
33
34
35
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)


const store = new Vuex.Store({
state: {
isLogin: false,
time: new Date().getMonth(),
},
mutations: {
clearLoginState(state) {
state.isLogin = false
},
loginSuccess(state) {
state.isLogin = true
}
},
actions: {

},
getters: {
timeNow(state) {
if(state.time+1<10) return '0' + (new Date().getMonth() + 1)
else return state.time
}
},
modules: {

}
})

export default store

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
<div id="wapper">
<button @click="Sub">获取时间</button>
</div>
</template>

<script>
export default {
data() {
return {
};
},
methods:{
Sub(){
console.log(`现在是${this.$store.getters.timeNow}月`)
}
}
};
</script>

<style scoped >
</style>

此外,各个getters 还可以作为参数相互传参

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
29
30
31
32
33
34
35
36
37
38
39
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)


const store = new Vuex.Store({
state: {
isLogin: false,
time: new Date().getMonth(),
},
mutations: {
clearLoginState(state) {
state.isLogin = false
},
loginSuccess(state) {
state.isLogin = true
}
},
actions: {

},
getters: {
timeMon(state) {
if(state.time+1<10) return '0' + (new Date().getMonth() + 1)+'月'
else return state.time+'月'
},
timeYear(state,getters){
let year = new Date().getFullYear()+'年'
return year+getters.timeMon
}
},
modules: {

}
})

export default store

同时,getters 里面还可以封装一个函数,供组件使用

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
29
30
31
32
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)


const store = new Vuex.Store({
state: {
year:new Date().getFullYear()
},
mutations: {
},
actions: {

},
getters: {
timeSeconds(state){
return Syear => {

if (Syear == state.year) return `匹配成功`

return '当前年份不等于vuex中存储的年份'
}
}
},
modules: {

}
})

export default store

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
<template>
<div id="wapper">
<input v-model="type"></input>
<button @click="Sub">提交</button>
<p>{{message}}</p>
</div>
</template>

<script>
export default {
data() {
return {
type:'',
message:''
};
},
methods:{
Sub(){
this.message = this.$store.getters.timeSeconds(this.type)
}
}
};
</script>

<style scoped >
</style>

mutations

vuex状态更新的唯一方式:提交mutations

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
29
30
31
32
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)


const store = new Vuex.Store({
state: {
date:'',
msg:'',
},
mutations: {
//第一种
//updateYear(state,year){
// state.year = year
//}

//第二种
updateYear(state,payload){
state.year = payload.year
state.msg = payload.msg
}
},
actions: {
},
getters: {
},
modules: {
}
})

export default store
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
29
30
31
32
33
<template>
<div id="wapper">
<input v-model="year"></input>
<button @click="Sub">提交</button>
</div>
</template>

<script>
export default {
data() {
return {
year:'',
message:'hello'
};
},
methods:{
Sub(){
//第一种提交风格
//第一个参数是mutations中定义的方法名 第二个参数,就是所传的指,又被称为 Payload
//this.$store.commit('updateYear',this.year)

this.$store.commit({
type:'updateYear',//在mutations 一个方法可以分为两个部分,一个是事件类型(方法名),一个是载荷(参数)
year:this.year,
msg:this.message
})
}
}
};
</script>

<style scoped >
</style>

actions

mutations 中的操作只能是同步操作,如需要进行异步操作则需要用到actions

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
29
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)


const store = new Vuex.Store({
state: {
msg:'hello ',
},
mutations: {
changeMsg(state,Cmsg){
state.msg = Cmsg
}
},
actions: {
changeMsgActions(context, payload) {
setTimeout(() => {
context.commit('changeMsg',payload.msgg)
}, 1000)
}
},
getters: {
},
modules: {
}
})

export default store
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
<template>
<div id="wapper">
<input v-model="year"></input>
<button @click="Sub">提交</button>
</div>
</template>

<script>
export default {
data() {
return {
year:'',
message:'hello'
};
},
methods:{
Sub(){
this.$store.dispatch({
type:'changeMsgActions',
msgg:'hello world'
})
}
}
};
</script>

<style scoped >
</style>

modules

当程序规模较大的时候,store对象可能变得非常臃肿,此时就可以使用modules对stroe进行划分成模块(modules),再对某个模块就行操作

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const moduleA = {
state:{
name:'fish'
},
mutations:{
updateName(state,payload){
state.name = payload
}
},
actions:{
//在模块中 使用context 指的是自己模块中的内容
updateName(context){
setTimeOut(()=>{
context.commit('updateName','awsl')
},1000)
}
},
getters:{
fullName(state){
return state.name + 'haha'
},
fullName2(state,getters){
return getters.fullName+'ababa'
},
fullName3(state,getters,rootState){
return getters.fullName+rootState.year
// 在模块中 可以使用 rootState 来调用 store对象中的属性
// rootState 为 根state 就是大对象 stroe 中的 state
}
}
}

const store = new Vuex.Store({
state: {
isLogin: false,
year: '2021'
},
mutations: {
},
actions: {

},
getters: {
},
modules: {
a:moduleA
}
})

export default store

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
29
30
31
32
33
34
35
36
37
<template>
<div id="wapper">
<h2>i am {{name}}</h2>
<input v-model="cName" type="text"></input>
<button @click="Sub">getName</button>
</div>
</template>

<script>
export default {
data() {
return {
name:'',
cName:''
};
},
methods:{
Sub(){
this.$stroe.commit('updateName','zhangsan')
// 普通提交
//提交以后,首先会去stroe对象中寻找对应方法,如果没有,则去模块中找,各个mutations 中的方法不能重名
},
created(){
this.name = this.$store.state.a.name
// 定义的模块最终会被放到 store 对象中的 state中去
// 通过 this.$store.state.a 即可拿到上面我们定义的模块,使用其中的属性,则直接点出属性名即可

// this.name = this.$store.getters.fullname
// this.name = this.$store.getters.fullname2
// 使用 getters 也是通过普通方式调用即可
}
}
};
</script>

<style scoped >
</style>

vuex 目录结构

随着项目越来越大,如果把vuex的代码全部写在index.js一个文件当中,就很难就行管理,因此,我们可以对里面的内容拆分成多个文件

将五个核心配置,单独封装成五个模块

在index.js 中导入模块即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

import mutations from './mutations.js'
import actions from './actions.js'
import getters from './getters.js'
import state from './state.js'

import moduleA from './modules/moduleA.js'

const store = new Vuex.Store({
state,
mutations,
actions,
getters,
modules: {
a: moduleA
}
})

export default store

使用exprot default 来导出对象

1
2
3
4
5
6
7
8
9
10
11
12
13
export default {

clearLoginState(state) {
state.isLogin = false
},
loginSuccess(state) {
state.isLogin = true
},
changeMsg(state, Cmsg) {
state.msg = Cmsg
}
}