Vuex基础

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

也就是将 Vue.js 程序中各个页面公用的数据和获取、改变这些数据的方法抽离出来,方便各个页面调用,以及页面之间的数据传输。

下面通过一个例子来讲解Vuex

我们首先创建一个Vue工程

我们假设有两个富豪榜,这两个富豪榜分属两个界面,通过组件注册,在一个主界面。

一、使用 props 属性传递参数

页面结构如下:

目录结构

我们在父页面 App.vuedata 属性中加入人员列表,并引入两个子页面,通过 v-bind 指令将 data 传递给子页面。

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="app">
<!-- 将 data 元素传递给子页面 -->
<salary-list-one v-bind:sendedSalaryList="salaryList"></salary-list-one>
<salary-list-two v-bind:sendedSalaryList="salaryList"></salary-list-two>
</div>
</template>
<script>
import salarylist1 from './components/salarylist1';
import salarylist2 from './components/salarylist2';
export default {
name: "app",
data() {
return {
salaryList: [{
name: "马云",
salaryAmount: 1000
},
{
name: "马化腾",
salaryAmount: 900
},
{
name: "李彦宏",
salaryAmount: 800
}
]
};
},
components: {
'salary-list-one': salarylist1,
'salary-list-two': salarylist2
}
};
</script>
<style scoped>
</style>

子页面通过 props 属性接收父页面传递过来的参数,并展示出来。

salarylist1.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
<template>
<div id="salary-list-fisrt">
<h2>财富榜</h2>
<ol>
// 通过 v-for 命令将其展示出来

<li v-for="salary in sendedSalaryList">
{{salary.name}}的工资是:{{salary.salaryAmount}}
</li>
</ol>
</div>
</template>
<script>
export default {
name: "salary-listfirst",
// 通过 props 属性接收父页面传来的参数

props: {
sendedSalaryList: {
type: Array,
required: true
}
}

}
</script>
<style>

</style>

salarylist2.vue 代码和上面的代码基本相似

运行结果如下:

运行结果

二、使用 Vuex 简化数据传递

虽然页面之间可以使用 props, $emit 等传递参数,但是这种参数的传递会面临以下问题

问题一 :多个视图依赖于同一状态。

问题二 :来自不同视图的行为需要变更同一状态。

对于问题一,传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力。

对于问题二,我们经常会采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝。以上的这些模式非常脆弱,通常会导致无法维护的代码。

因此,我们为什么不把组件的共享状态抽取出来,以一个全局单例模式管理呢?

在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为!

另外,通过定义和隔离状态管理中的各种概念并强制遵守一定的规则,我们的代码将会变得更结构化且易维护

如果之前没有安装 vuex,使用下面的命令安装

1
npm install vuex --save

在项目根目录下新建 store/store.js 文件,这个文件中保存的就是这个应用中需要共享的内容, 而且整个应用中只有一个。

main.js 文件中引入 vuex

1
2
3
4
5
6
7
8
9
10
11
import Vue from 'vue'
import App from './App.vue'
import {store} from './store/store'


Vue.config.productionTip = false

new Vue({
store:store,
render: h => h(App),
}).$mount('#app')

1. State

state 类似于 Vue 实例中的 data 属性,不同的是 state 是共享的。

现在将刚才 App.vue 中的 data 保存在store.js 中,将 App.vue 中保存的数据移除。

现在,两个财富榜都没有了数据,如图:

没有数据

现在改为从 store 请求数据

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

Vue.use(Vuex);

export const store = new Vuex.Store({
state: {
storeSalaryList: [{
name: "马云",
salaryAmount: 1000
},
{
name: "马化腾",
salaryAmount: 900
},
{
name: "李彦宏",
salaryAmount: 800
}
]
}
});

在 财富榜2 中引入获取 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>
<!--salarylist2.vue -->
<div id="salary-list-fisrt">
<h2>财富榜2</h2>
<ol>
<li v-for="salary in salaryList ">
{{salary.name}}的工资是:{{salary.salaryAmount}}
</li>
</ol>
</div>
</template>
<script>
export default {
name: "salary-list-first",
computed: {
salaryList() {
// 通过 computed 属性,获取到 store.js 中的数据,并返回

return this.$store.state.storeSalaryList;
}
}
}
</script>
<style>

</style>

在 App.vue 中去掉 v-bind 指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<template>
<div id="app">
<salary-list-one ></salary-list-one>
<salary-list-two ></salary-list-two>
</div>
</template>
<script>
import salarylist1 from './components/salarylist1';
import salarylist2 from './components/salarylist2';
export default {
name: "app",
data() {
return {

};
},
components:{
'salary-list-one':salarylist1,
'salary-list-two':salarylist2
}
};
</script>
<style scoped>
</style>

运行结果如下:

财富榜2有数据

如果在 salarylist1.vue 中也加入上面的 store 引用,就可以连个财富榜就可以全部展示。

2.getter

在一些情况下,当获取到 state 的数据之后,我们希望进行一些加工处理再进行展示。

现在,我们将上面每个人的工资翻倍,再增加 美元($)符号。

修改 salarylist1.vuesalarylist2.vue 代码,在 computed 属性中增加,doubleSalary 属性

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
<template>
<div id="salary-list-fisrt">
<h2>财富榜</h2>
<ol>
<li v-for="salary in doubleSalary">
{{salary.name}}的工资是:{{salary.salaryAmount}}
</li>
</ol>
</div>
</template>
<script>
export default {
computed: {
salaryList() {
return this.$store.state.storeSalaryList;
},
// doubleSalary 属性对每个人 state 的数据加工后进行返回
doubleSalary() {
var afterDoubleSalary =
this.$store.state.storeSalaryList.map(salary => {
return {
name: salary.name,
salaryAmount: salary.salaryAmount * 2 + " " + "$"

};
});
return afterDoubleSalary;
}
},

}
</script>
<style>

</style>

运行结果如下

工资翻倍

以上的代码虽然对 state 属性进行了加工之后返回,但是有一定的局限性,如果有100个页面都要这样处理,是不是就要将 doubleSalary 属性写100遍?这样显然是不合理的,为了解决这个问题,可以 doubleSalary 属性写进 store.js 作为一个 getter 方法。

store.js 中增加一个getter 方法

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

Vue.use(Vuex);

export const store = new Vuex.Store({
state: {
storeSalaryList: [{
name: "马云",
salaryAmount: 1000
},
{
name: "马化腾",
salaryAmount: 900
},
{
name: "李彦宏",
salaryAmount: 800
}
]
},
getters: {
// 增加一个 getter 方法,用于返回加工后的 工资
doubleSalaryGetter: (state) => {
var afterDoubleSalary =
state.storeSalaryList.map(salary => {
return {
name: salary.name,
salaryAmount: salary.salaryAmount * 2 + " " + "$"

};
});
return afterDoubleSalary;
}
}
});

修改 salarylist1.vuesalarylist2.vue 代码,在 computed 属性中增加,doubleSalaryByGetter 属性,在这个属性中,调用 store.js 中的 getter 返回结果。

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="salary-list-fisrt">
<h2>财富榜</h2>
<ol>
<li v-for="salary in doubleSalaryByGetter">
{{salary.name}}的工资是:{{salary.salaryAmount}}
</li>
</ol>
</div>
</template>
<script>
export default {
computed: {
salaryList() {
return this.$store.state.storeSalaryList;
},
// 在这里调用 store.js 中的方法。
doubleSalaryByGetter() {
return this.$store.getters.doubleSalaryGetter;
}
},

}
</script>
<style>
</style>

工资翻倍

如果我们 还有一个需求:计算工资总额,可以在 getter 新增加一个 totalSalary 方法

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: {
storeSalaryList: [{
name: "马云",
salaryAmount: 1000
},
{
name: "马化腾",
salaryAmount: 900
},
{
name: "李彦宏",
salaryAmount: 800
}
]
},
getters: {
doubleSalaryGetter: (state) => {
var afterDoubleSalary = state.storeSalaryList.map(salary => {
return {
name: salary.name,
salaryAmount: salary.salaryAmount * 2 + " " + "$"

};
});
return afterDoubleSalary;
},
// 在这里增加一个 计算工资总额的方法

totalSalary: (state) => {
var sum = 0
state.storeSalaryList.forEach(element => {
sum += element.salaryAmount;
});
return sum*2;
}
}
});

修改 salarylist1.vue 代码,在 computed 属性中增加,totalSalaryByGetter 属性,在这个属性中,调用 store.js 中的 getter 返回结果。

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
<template>
<div id="salary-list-fisrt">
<h2>财富榜</h2>
<ol>
<li v-for="salary in doubleSalaryByGetter">
{{salary.name}}的工资是:{{salary.salaryAmount}}
</li>
</ol>
<span>工资总额是: {{totalSalaryByGetter}}</span>
</div>
</template>
<script>
export default {
computed: {
salaryList() {
return this.$store.state.storeSalaryList;
},
doubleSalaryByGetter() {
return this.$store.getters.doubleSalaryGetter;
},
// 增加获取工资总额的方法
totalSalaryByGetter() {
return this.$store.getters.totalSalary;
}
},

}
</script>
<style>
</style>

工资总额

我们通过在当前页面调用 store.jsgetter 方法,可以返回想要的结果。但是发现,在每个页面中,都要写调用写一个方法来调用 getter 也不是很方便。

Vuex 为我们提供了一个 mapGetters 辅助函数,可以用来获取getter

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
<template>
<div id="salary-list-fisrt">
<h2>财富榜2</h2>
<!--
<ol>
<li v-for="salary in doubleSalaryGetter ">
{{salary.name}}的工资是:{{salary.salaryAmount}}
</li>
</ol>
<span>工资总额是:{{totalSalary}}</span>
-->
<ol>
<li v-for="salary in myDoubleSalaryGetter ">
{{salary.name}}的工资是:{{salary.salaryAmount}}
</li>
</ol>
<span>工资总额是:{{myTotalSalary}}</span>
</div>
</template>
<script>
import {
mapGetters
} from 'vuex';
export default {
name: "salary-list-two",

computed: {
salaryList() {
return this.$store.state.storeSalaryList;
},
doubleSalaryByGetter() {
return this.$store.getters.doubleSalaryGetter;
},
/**
...mapGetters(
// 注意这里是个数组
[
'doubleSalaryGetter','totalSalary'
]
)*/

// ...mapGetters的另一种写法,通过这种方法可以给 getter 起别名
...mapGetters(
// 注意这里是一个对象
{
myDoubleSalaryGetter: 'doubleSalaryGetter',
myTotalSalary: 'totalSalary'

})
}
}
</script>
<style>
</style>

运行结果如下:

运行结果

3.mutations

现在我们添加一个按钮,这个按钮的作用是,给 state 中的 storeSalaryList 增加工资,首先可以使用一个方法来改变 state

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
43
44
<template>
<div id="app">
<salary-list-one></salary-list-one>
<salary-list-two></salary-list-two>
<button @click="moreSalary()">加工资</button>
<button @click="getAmount()">显示工资</button>

</div>
</template>
<script>
import salarylist1 from './components/salarylist1';
import salarylist2 from './components/salarylist2';
export default {
name: "app",
data() {
return {

};
},
components: {
'salary-list-one': salarylist1,
'salary-list-two': salarylist2
},
methods: {
// 这个方法用来只增加工资

moreSalary() {
this.$store.state.storeSalaryList.forEach(element => {
element.salaryAmount += 100;
});
},
// 这个方法用来显示 state 的工资内容

getAmount() {
this.$store.state.storeSalaryList.forEach(element => {
console.log(element.salaryAmount);
})
}
}
};
</script>
<style scoped>

</style>

运行结果:

分别点击 加工资显示工资 按钮

加工资

(注:这里之所以点击一下加工资按钮每个人的工资增加 200 是因为,在两个子页面用的属性是 doubleSalaryGetter),由此可见 state 可见发生了变化。

但是直接调用方法,无法记录 store 中各种属性的变化,如果用 mutatios ,就可以使用 vue 的开发工具 Vue.js devtools,可以直观地观察 store 中的属性值变化。

store.js 增加一个 mutations 节点,并增加一个 moreSalaryMutation 属性

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

Vue.use(Vuex);

export const store = new Vuex.Store({
state: {
storeSalaryList: [{
name: "马云",
salaryAmount: 1000
},
{
name: "马化腾",
salaryAmount: 900
},
{
name: "李彦宏",
salaryAmount: 800
}
]
},
getters: {
doubleSalaryGetter: (state) => {
var afterDoubleSalary = state.storeSalaryList.map(salary => {
return {
name: salary.name,
salaryAmount: salary.salaryAmount * 2 + " " + "$"

};
});
return afterDoubleSalary;
},
totalSalary: (state) => {
var sum = 0
state.storeSalaryList.forEach(element => {
sum += element.salaryAmount;
});
return sum * 2;
}
},
mutations: {
// 这个方法用来更改 state

moreSalaryMutation: (state) => {
state.storeSalaryList.forEach(element=>{
element.salaryAmount += 100;
})
}
}
});

现在再增加一个按钮,使用mutations增加工资

AppVue

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
<template>
<div id="app">
<salary-list-one></salary-list-one>
<salary-list-two></salary-list-two>
<button @click="moreSalary()">加工资</button>
<button @click="getAmount()">显示工资</button>


<button @click="moreSalaryByMutatios()">使用matatios增加工资</button>

</div>
</template>
<script>
import salarylist1 from './components/salarylist1';
import salarylist2 from './components/salarylist2';
export default {
name: "app",
data() {
return {

};
},
components: {
'salary-list-one': salarylist1,
'salary-list-two': salarylist2
},
methods: {
moreSalary() {
this.$store.state.storeSalaryList.forEach(element => {
element.salaryAmount += 100;
});
},
getAmount() {
this.$store.state.storeSalaryList.forEach(element => {
console.log(element.salaryAmount);
})
},
// 这个方法调用 commit 来更改 state

moreSalaryByMutatios() {
this.$store.commit("moreSalaryMutation");
}
}
};
</script>
<style scoped>

</style>

运行结果如下:

可以使用vue-tools观察store

值得注意的是,使用 commit 来更改 state ,我们可以借助Vue.js devtools很清晰地观测 state 的变化。

在Vuex的官方文档中有一句话

The only way to actually change state in a Vuex store is by committing a mutation.

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。

在上面的例子中,我们发现不仅 commit 可以修改 state的值,通过一个普通的函数调用 moreSalary 方法也可以更改 state 的值,这好像和文档描述不相符。但是,如果在 store 创建的时候,申明为严格模式,再次调用moreSalary方法,就会报错。

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
41
42
43
44
45
46
47
48
49
50
51
52
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export const store = new Vuex.Store({
// 在这里增加 严格模式
strict:true,

state: {

storeSalaryList: [{
name: "马云",
salaryAmount: 1000
},
{
name: "马化腾",
salaryAmount: 900
},
{
name: "李彦宏",
salaryAmount: 800
}
]
},
getters: {
doubleSalaryGetter: (state) => {
var afterDoubleSalary = state.storeSalaryList.map(salary => {
return {
name: salary.name,
salaryAmount: salary.salaryAmount * 2 + " " + "$"

};
});
return afterDoubleSalary;
},
totalSalary: (state) => {
var sum = 0
state.storeSalaryList.forEach(element => {
sum += element.salaryAmount;
});
return sum * 2;
}
},
mutations: {
moreSalaryMutation: (state) => {
state.storeSalaryList.forEach(element=>{
element.salaryAmount += 100;
})
}
}
});

再次点击加工资,就会出现报错

严格模式

4. actions

Action 类似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态。

    • Action 可以包含任意异步操作。

现在我们将点击 使用matatios增加工资 改为5秒后产生效果。
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export const store = new Vuex.Store({
strict:true,

state: {

storeSalaryList: [{
name: "马云",
salaryAmount: 1000
},
{
name: "马化腾",
salaryAmount: 900
},
{
name: "李彦宏",
salaryAmount: 800
}
]
},
getters: {
doubleSalaryGetter: (state) => {
var afterDoubleSalary = state.storeSalaryList.map(salary => {
return {
name: salary.name,
salaryAmount: salary.salaryAmount * 2 + " " + "$"

};
});
return afterDoubleSalary;
},
totalSalary: (state) => {
var sum = 0
state.storeSalaryList.forEach(element => {
sum += element.salaryAmount;
});
return sum * 2;
}
},
mutations: {
moreSalaryMutation: state => {
// 五秒之后加工资。

setTimeout(function(){
state.storeSalaryList.forEach(element=>{
element.salaryAmount += 100;
})
},5000)
/*/state.storeSalaryList.forEach(element=>{
element.salaryAmount += 100;
})*/
}
}
});

运行结果如下,等待5秒之后,虽然页面数值发生了变化,但是Vue.js dev-tools 却没有发生变化,而且还报错了。

没有变化

报错如下

报错

对此 Evan You 亲自给出了解释

给出解释

store.js 中增加 actions 节点,并增加一个 moreSalaryAction 方法

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export const store = new Vuex.Store({
strict:true,

state: {

storeSalaryList: [{
name: "马云",
salaryAmount: 1000
},
{
name: "马化腾",
salaryAmount: 900
},
{
name: "李彦宏",
salaryAmount: 800
}
]
},
getters: {
doubleSalaryGetter: (state) => {
var afterDoubleSalary = state.storeSalaryList.map(salary => {
return {
name: salary.name,
salaryAmount: salary.salaryAmount * 2 + " " + "$"

};
});
return afterDoubleSalary;
},
totalSalary: (state) => {
var sum = 0
state.storeSalaryList.forEach(element => {
sum += element.salaryAmount;
});
return sum * 2;
}
},
mutations: {
moreSalaryMutation: state => {
// setTimeout(function(){
state.storeSalaryList.forEach(element=>{
element.salaryAmount += 100;
})
// },5000)
/*/state.storeSalaryList.forEach(element=>{
element.salaryAmount += 100;
})*/
}
},
actions:{
// 这个方法调用上面的 mutations 里边的 moreSalaryMutation
// 点击3秒之后,运行mutation

moreSalaryAction:(context)=>{
setTimeout(function() {
context.commit("moreSalaryMutation");

},3000)

}
}
});

在 App.vue 中增加一个按钮 和 方法,点击按钮通过方法访问action

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<template>
<div id="app">
<salary-list-one></salary-list-one>
<salary-list-two></salary-list-two>
<button @click="moreSalary()">加工资</button>
<button @click="getAmount()">显示工资</button>


<button @click="moreSalaryByMutatios()">使用matatios增加工资</button>
<!-- 增加方法来调用 action -->

<button @click="moreSalaryByActions()">使用actions增加工资</button>

</div>
</template>
<script>
import salarylist1 from './components/salarylist1';
import salarylist2 from './components/salarylist2';
export default {
name: "app",
data() {
return {

};
},
components: {
'salary-list-one': salarylist1,
'salary-list-two': salarylist2
},
methods: {
moreSalary() {
this.$store.state.storeSalaryList.forEach(element => {
element.salaryAmount += 100;
});
},
getAmount() {
this.$store.state.storeSalaryList.forEach(element => {
console.log(element.salaryAmount);
})
},
moreSalaryByMutatios() {
this.$store.commit("moreSalaryMutation");
//this.$store.dispatch("moreSalaryAction");
},
moreSalaryByActions() {
// 通过此方法调用action

this.$store.dispatch("moreSalaryAction");
}

}
};
</script>
<style scoped>

</style>

点击后我们发现 dev-tools 左边的方法记录和右边的 state 的值同时 改变,而且没有报错

没有报错

Action中也可以传递参数。

我们设置一个工资增加的数目,通过 playload 来进行传递

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<template>
<div id="app">
<salary-list-one></salary-list-one>
<salary-list-two></salary-list-two>
<button @click="moreSalary()">加工资</button>
<button @click="getAmount()">显示工资</button>


<button @click="moreSalaryByMutatios()">使用matatios增加工资</button>
// 设置每次增加的数量

<button @click="moreSalaryByActions(256)">使用actions增加工资</button>

</div>
</template>
<script>
import salarylist1 from './components/salarylist1';
import salarylist2 from './components/salarylist2';
export default {
name: "app",
data() {
return {

};
},
components: {
'salary-list-one': salarylist1,
'salary-list-two': salarylist2
},
methods: {
moreSalary() {
this.$store.state.storeSalaryList.forEach(element => {
element.salaryAmount += 100;
});
},
getAmount() {
this.$store.state.storeSalaryList.forEach(element => {
console.log(element.salaryAmount);
})
},
moreSalaryByMutatios() {
this.$store.commit("moreSalaryMutation");
//this.$store.dispatch("moreSalaryAction");
},
// 传递参数

moreSalaryByActions(amount) {

this.$store.dispatch("moreSalaryAction", amount);
}

}
};
</script>
<style scoped>

</style>

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export const store = new Vuex.Store({
strict:true,

state: {

storeSalaryList: [{
name: "马云",
salaryAmount: 1000
},
{
name: "马化腾",
salaryAmount: 900
},
{
name: "李彦宏",
salaryAmount: 800
}
]
},
getters: {
doubleSalaryGetter: (state) => {
var afterDoubleSalary = state.storeSalaryList.map(salary => {
return {
name: salary.name,
salaryAmount: salary.salaryAmount * 2 + " " + "$"

};
});
return afterDoubleSalary;
},
totalSalary: (state) => {
var sum = 0
state.storeSalaryList.forEach(element => {
sum += element.salaryAmount;
});
return sum * 2;
}
},
mutations: {
moreSalaryMutation: (state,amount) => {
// setTimeout(function(){
state.storeSalaryList.forEach(element=>{
element.salaryAmount += amount;
})
// },5000)
/*/state.storeSalaryList.forEach(element=>{
element.salaryAmount += 100;
})*/
}
},
actions:{
// 传递参数

moreSalaryAction:(context,amount)=>{
setTimeout(function() {
context.commit("moreSalaryMutation",amount);

},3000)

}
}
});

运行结果:工资以指定数值增减, 通过vue-tools 可以观测到 playload的变化

指定数值

类似于 mapGetters, 可以调用 mapActions 来应对有很多 action 时的情况

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<template>
<div id="app">
<salary-list-one></salary-list-one>
<salary-list-two></salary-list-two>
<button @click="moreSalary()">加工资</button>
<button @click="getAmount()">显示工资</button>


<button @click="moreSalaryByMutatios()">使用matatios增加工资</button>
<button @click="moreSalaryByActions(256)">使用actions增加工资</button>

<!--
<button @click="moreSalaryAction(256)">使用mapActions增加工资</button>
-->
<button @click="myMoreSalaryAction(256)">使用mapActions增加工资</button>

</div>
</template>
<script>
import salarylist1 from './components/salarylist1';
import salarylist2 from './components/salarylist2';
import {
mapActions
} from 'vuex'

export default {
name: "app",
data() {
return {

};
},

components: {
'salary-list-one': salarylist1,
'salary-list-two': salarylist2
},
methods: {
moreSalary() {
this.$store.state.storeSalaryList.forEach(element => {
element.salaryAmount += 100;
});
},
getAmount() {
this.$store.state.storeSalaryList.forEach(element => {
console.log(element.salaryAmount);
})
},
moreSalaryByMutatios() {
this.$store.commit("moreSalaryMutation");
//this.$store.dispatch("moreSalaryAction");
},
moreSalaryByActions(amount) {
this.$store.dispatch("moreSalaryAction", amount);
},
...mapActions([

// `mapActions` 也支持载荷:
'moreSalaryAction' // 将 `this.moreSalaryAction(amount)` 映射为 `this.$store.dispatch('moreSalaryAction', amount)`
]),
// mapActions 的 第二种写法
...mapActions({
myMoreSalaryAction:'moreSalaryAction'
})

}
};
</script>
<style scoped>

</style>

mapactions

作者

Bruce Liu

发布于

2018-12-11

更新于

2022-11-12

许可协议

You need to set install_url to use ShareThis. Please set it in _config.yml.
You forgot to set the business or currency_code for Paypal. Please set it in _config.yml.

评论

You forgot to set the shortname for Disqus. Please set it in _config.yml.