Devtools安装

在使用vuex之前,我们先来安装一个vue开发工具,vue.js devtools,这是vue的官方调试工具,vuex也集成在其中

谷歌浏览器 -> 更多工具 -> 扩展程序 -> 打开谷歌网上应用店 -> 搜索vue.js devtools -> 添加到chrome

以上步骤需要科学上网

添加完这个插件之后,创建一个vue项目,勾选上vuex,我们就可以在调试控制台中看到这个插件的效果了

可以在调试控制台的导航栏选择vue,然后选择vuex,当然现在这里看不到什么东西,因为我们没有添加什么状态管理

vue.js devtools在谷歌商店里有两个,安装人多那个更好看,功能也更多一点,建议选那个

Vuex简单使用

创建完vue工程后,我们可以看到勾选了vuex之后,src文件夹里面多了一个store文件夹,里面有个js文件,内含代码如下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {
},
modules: {
}
})

其中state是用来存放数据的地方,mutations和actions用于存放管理数据的方法,分别用于管理同步修改和异步修改,modules则是用来将store划分模块,每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块来避免单一状态树变得过于臃肿

State

我们先来简单地使用一下state,在里面创建一个msg

1
2
3
4
5
6
7
8
9
10
11
export default new Vuex.Store({
state: {
msg: "Hello World"
},
mutations: {
},
actions: {
},
modules: {
}
})

然后我们就能在devtools里面看到这个

在其它的组件里面我们可以很方便地使用这个公共数据 (通过$store.state)

比如我们在home页面中写入如下代码

1
2
3
4
5
<template>
<div class="home">
{{$store.state.msg}}
</div>
</template>

就可以直接使用这个数据

Getters

getters是vuex中的计算属性 (和vue中的computed相同),我们来做一个简单的使用测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
export default new Vuex.Store({
state: {
msg: "Hello World",
scores: [12, 59, 89, 92, 42, 99, 91, 76]
},
getters:{
highScore:function(state){
return state.scores.filter(item=>item>=80);
}
}
mutations: {
},
actions: {
},
modules: {
}
})

在组件中可以通过$store.getters.highScore来使用它

映射辅助函数

前面我们举了使用state和getters的两个例子,可以看到,想要在组件中使用vuex管理的内容要写的属性名特别的长 (比如$store.getters.highScore)

这里我们可以利用mapState来做映射使得使用更方便,比如说我们要使用$store.state.msg$store.state.scores,可以这么写

1
2
3
4
5
6
7
8
9
10
11
12
13
<template>
<div class="home">
{{msg}}{{scores}}
</div>
</template>

<script>
import {mapState} from 'vuex'
export default {
name: 'Home',
computed: mapState(['msg','scores'])
}
</script>

当然也可以跟其它的计算属性一起使用 (析构来去掉外边的括号)

1
2
3
4
5
6
computed: {
...mapState(['msg','scores']),
three: function(){
return this.one + this.two
}
}

如果我们希望把传过来的msg变量改个名字,则可以这么写

1
2
3
4
5
6
7
8
9
computed: {
...mapState({
msg123: function(state){
return state.msg
},
// 简写
msg111: state=>state.msg
})
}

同理,对于getters也有mapGetters

使用方法不能说是毫无关系,只能说是一摸一样了

1
2
3
4
5
6
7
8
9
computed:{
// 采用原名
...mapGetters(['lowerScore', 'higherScore'])
// 自命名
...mapGetters({
lsscore: 'lowerScore',
hscore: 'higherScore'
})
}

Mutations

vuex的store中的状态只能通过提交mutation的方式更改,mutation中的方法默认接受state作为第一个参数

举个例子,我们想要通过点击一个按钮修改scores中的值

我们在store中写一个change函数

1
2
3
4
5
6
mutations: {
change:function(state, pos){
state.scores[pos] = 0
state.scores.shift()
}
},

然后在组件中通过commit来传参和执行

1
2
3
4
5
methods:{
click:function(){
this.$store.commit("change", 2)
}
}

同理,映射可以让mutations的使用也更为简单,使用方法和之前的非常相似,需要引入mapMutations

1
2
3
4
5
methods:{
...mapMutations({
click: 'change'
})
}

然后我们就可以直接使用这个click

1
<button @click=click(2)>test</button>

Actions

我们之前提到过Actions可以异步修改数据,但是实际上,它提交的是mutation,而不是直接修改状态,但是它允许任何异步操作,一般用于做ajax请求等,在组件中用this.$store.dispatch来提交,action也可以使用映射,需要引入mapActions,使用方法同mapMutations

Modules

modules就是一个为了让状态树看起来不那么臃肿的功能,比如我可以嵌套两个子module

1
2
3
4
5
6
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})

然后分别去写那两个modules,功能和之前简绍的vuex的store内容相同

1
2
3
4
5
6
const moduleA = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... },
getters: { ... }
}

在组件中使用时通过$store.state.a$store.state.b来获取两个store分块的信息