Vue2.0 Vuex集中式储存管理

引用官网的话:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态

这里是它的官方文档:https://vuex.vuejs.org/zh-cn/

我们可以很直观的看到有五个方法:

State 可以简单的理解为组件的 data,不过 state 是全局唯一的。

Getters 可以在模板中静态的显示数据。换句话说,getters 可以读取数据,但不能改变状态。

Mutations 允许更新状态,但永远是同步的。Mutations 是 store 中改变状态数据的唯一方式。

Actions 允许异步更新状态,但是需要使用一个已经存在的 mutation 。如果你需要以特定的顺序同时执行不同的 mutations 会非常有用。

Modules Vuex 允许我们将 store 分割到模块(module)。每个模块拥有自己的 state、mutation、action、getters、甚至是嵌套子模块——从上至下进行类似的分割

一、简单 demo

搭建一个 vue-cli,新建一个 store.js
vuex.png

在 main.js 种先引入 vuex

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'

import {store} from './vuex/store'

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
el: '#app',
router,
// 注意这里要注入到vue实例
store,
template: '<App/>',
components: { App }
})

在 store.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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export const store = new Vuex.Store({
state: {
counter: 8,
weather: 'rainy',
time: '20:40'
},
// 展示内容,无法改变状态
getters: {
counter: state => {
return state.counter
},
weather: state => {
return state.weather
},
time: state => {
return state.time
}
},
//mutations 永远是同步的
mutations: {
// 显示传递的载荷 payload, 用 num 表示
increment: (state, num) => {
state.counter += num;
},
decrement: (state, num) => {
state.counter = state.counter - num;
}
},
// actions 可异步
actions: {
acDecremen:({commit}, asyncNum) => {
setTimeout(() => {
// asyncNum 对象可以是静态值
commit('decrement', asyncNum.num);
}, 1000);
}
},
});

在 app.vue 拿到数据

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
<template>
<div id="app">
{{counter}} || {{weather}} || {{time}}
<button @click='add'> +1 </button>
<button @click='increment'> -1 </button>
</div>
</template>

<script>
export default {
computed: {
counter() {
return this.$store.getters.counter
},
weather() {
return this.$store.getters.weather
},
time() {
return this.$store.getters.time
}
},
methods: {
add(){
this.$store.commit('increment',1)
},
increment(){
this.$store.dispatch('acDecremen',{num:1})
}
}
}
</script>

<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>

运行:一个按钮立即加一(mutations),一个一秒后减一(actions)

vuex.gif

二、利用 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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/*App.vue*/

import music from './components/music'
import movie from './components/movie'
new Vue({
//..........
components:{
music,
movie
}
})

/*music.vue*/

<template>
<div class = 'music'>
I'm music,my counter is {{counter}}
</div>
</template>
<script>
export default{
computed:{
counter() {
return this.$store.getters.counter
},
}
};
</script>
<style>
</style>

/*movie.vue*/

<template>
<div class = 'movie'>
I'm movie,my counter is {{counter}}
</div>
</template>
<script>
export default{
computed:{
counter() {
return this.$store.getters.counter
},
}
};
</script>
<style>
</style>

然后在 app.vue 种直接使用模板,就可以同步更新数据了

vuex.gif

三、Module

感觉这个功能有点像命名空间的功能,其中的 getters,mutations,actions 现在仍然注册在全局命名空间————这样保证了多个模块能够响应同一 mutation 或 action。

即 getters,mutations,actions 的名字不可以重复

修改 store.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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

const moduleA = {
state: {
name: 'moduleA'
},
getters: {
aname: state => state.name
},
mutations: {
setBName: state => state.name = 'new modulesA'
},
actions: {
acSetAName: state => state.name = 'ac moudleA'
}
}
const moduleB = {
state: {
name: 'moduleB'
},
getters: {
bname: state => state.name
},
mutations: {
setBName: state => state.name = 'new modulesB'
},
actions: {
acSetBName: state => state.name = 'ac moudleB'
}
}

export const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})

想拿到 moduleA 的 name 的值可以不用 getters,直接
this.$store.state.a.name
其他方法的调用都一样,因为都是用同样的方法名