0
点赞
收藏
分享

微信扫一扫

Vuex--mapState, mapGetters, mapActions, mapMutations--使用/教程/实例


简介

说明

        本文用示例介绍Vue的vuex的组件绑定的辅助函数的用法。包括:mapState, mapGetters, mapActions, mapMutations。

官网

​​State | Vuex​​

​​API 参考 | Vuex​​

示例

公共代码

需求:点击一个组件按钮,增加另一个组件的数量。

router/index.js

import Vue from 'vue'
import Router from 'vue-router'
import CompA from "@/components/CompA";

Vue.use(Router)

export default new Router({
routes: [
{
path: '/compA',
name: 'compA',
component: CompA,
}
],
})

store/CounterStore.js  //计数器store

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);
const couterStore = new Vuex.Store(
{
state: {
count1: 0
},
mutations: {
incr1(state) {
state.count1++;
},
decr1(state) {
state.count1--;
},
},
}
);

export default couterStore;

components/CompA.vue

因为vue是单页面应用,所以用此组件引入其余两个组件。

<template>
<div class="compA">
<child-one></child-one>
<hr>
<child-two></child-two>

</div>
</template>

<script>
import ChildOne from "@/components/ChildOne";
import ChildTwo from "@/components/ChildTwo";

export default {
components: {ChildOne, ChildTwo},
data() {
return {
}
},
}
</script>

<style scoped>

</style>

components/ChildOne.vue  //发送事件

<template>
<div class="childOne">
<h1>childOne</h1>
<button @click="incr1">增加:兄弟组件(ChildTwo)</button>
<button @click="decr1">减少:兄弟组件(ChildTwo)</button>
</div>
</template>

<script>

export default {
data() {
return {
payload: {
amount: 5
}
}
},
methods:{
incr1() {
this.$store.commit('incr1')
},
decr1() {
this.$store.commit('decr1')
},
}
}
</script>

<style scoped>
</style>

components/ChildTwo.vue   //接收事件

<template>
<div class="childTwo">
<h1>childTwo</h1>
收到的事件内容:{{msg}}
</div>
</template>

<script>

export default {
data() {
return {
}
},
computed:{
msg() {
return this.$store.state.count1;
}
}
}
</script>

<style scoped>

</style>

测试

访问:​​http://localhost:8080/#/compA​​ 

mapState

简介

当一个组件需要获取多个状态时,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,可以使用mapState辅助函数帮助生成计算属性

// 在单独构建的版本中辅助函数为 Vuex.mapState
import { mapState } from 'vuex'

export default {
// ...
computed: mapState({
// 箭头函数可使代码更简练
count: state => state.count,

// 传字符串参数 'count' 等同于 `state => state.count`
// 下边这行等价于: countAlias: state => state.count
countAlias: 'count',


// 为了能够使用 `this` 获取局部状态,必须使用常规函数
countPlusLocalState (state) {
return state.count + this.localCount
}
})
}

当映射的计算属性的名称与 state 的子节点名称相同时,也可以给 mapState 传一个字符串数组

computed: mapState([
// 映射 this.count 为 store.state.count
'count'
])

//等价于
//computed: {
// count(){
// return this.$store.state.count
// }
//}

改造“公共代码”

<template>
<div class="childTwo">
<h1>childTwo</h1>
收到的事件内容:{{msg}} <br>
count1Alias: {{count1Alias}} <br>
事件加本地值: {{countPlusLocalState}} <br>
</div>
</template>

<script>
import {mapState} from 'vuex'
export default {
data() {
return {
localCount: 5,
cnt: 0
}
},
// 原来的写法
// computed:{
// msg() {
// return this.$store.state.count1;
// }
// }
computed: mapState({
msg: state => state.count1,
//上边这行也可以这么写:
//msg: 'count1'
count1Alias: 'count1',
countPlusLocalState(state) {
return this.msg + this.localCount
}
})
}
</script>

<style scoped>

</style>

测试

访问:​​http://localhost:8080/#/compA​​

mapGetters

简介

mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性:

import { mapGetters } from 'vuex'

export default {
// ...
computed: {
// 使用对象展开运算符将 getter 混入 computed 对象中
...mapGetters([
'doneTodosCount',
'anotherGetter',
// ...
])
}
}

如果想将一个 getter 属性另取一个名字,使用对象形式:

mapGetters({
// 映射 `this.doneCount` 为 `store.getters.doneTodosCount`
doneCount: 'doneTodosCount'
})

改写“公共代码”

store/CounterStore.js

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);
const couterStore = new Vuex.Store(
{
state: {
count1: 0
},
mutations: {
incr1(state) {
state.count1++;
},
decr1(state) {
state.count1--;
},
},
getters: {
doubleCount1: state => {
return state.count1 * 2;
}
}
}
);

export default couterStore;

components/ChildTwo.vue

<template>
<div class="childTwo">
<h1>childTwo</h1>
收到的事件内容:{{msg}} <br>
doubleCount1: {{doubleCount1}}
</div>
</template>

<script>
import {mapGetters} from 'vuex'
export default {
data() {
return {
}
},
computed:{
msg() {
return this.$store.state.count1;
},
...mapGetters(['doubleCount1'])
// 也就是:
// doubleCount1() {
// return this.$store.getters.doubleCount1;
// }
}
}
</script>

<style scoped>

</style>

测试

访问:​​http://localhost:8080/#/compA​​

mapMutations

简介

可以在组件中使用 this.$store.commit('xxx') 提交 mutation,或者使用 mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用(需要在根节点注入 store)

import { mapMutations } from 'vuex'

export default {
// ...
methods: {
...mapMutations([
'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`

// `mapMutations` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
]),
...mapMutations({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
})
}
}

改造“公共代码”

<template>
<div class="childOne">
<h1>childOne</h1>
<button @click="incr1">增加:兄弟组件(ChildTwo)</button>
<button @click="decr1">减少:兄弟组件(ChildTwo)</button>
</div>
</template>

<script>
import {mapMutations} from 'vuex'
export default {
data() {
return {
payload: {
amount: 5
}
}
},
methods: {
// 原来的写法
// incr1() {
// this.$store.commit('incr1')
// },
// decr1() {
// this.$store.commit('decr1')
// },
...mapMutations(['incr1', 'decr1'])
}
}
</script>

<style scoped>
</style>

测试

访问: ​​http://localhost:8080/#/compA​​

使用别名映射

<template>
<div class="childOne">
<h1>childOne</h1>
<button @click="incrAlias">增加:兄弟组件(ChildTwo)</button>
<button @click="decrAlias">减少:兄弟组件(ChildTwo)</button>
</div>
</template>

<script>
import {mapMutations} from 'vuex'
export default {
data() {
return {
}
},
methods: {
...mapMutations({incrAlias: 'incr1', decrAlias: 'decr1'})
}
}
</script>

<style scoped>
</style>

测试

访问: ​​http://localhost:8080/#/compA​​

数组与别名同时使用

<template>
<div class="childOne">
<h1>childOne</h1>
<button @click="incr1">增加:兄弟组件(ChildTwo)</button>
<button @click="decrAlias">减少:兄弟组件(ChildTwo)</button>
</div>
</template>

<script>
import {mapMutations} from 'vuex'
export default {
data() {
return {
}
},
methods: {
...mapMutations({...mapMutations(['incr1']), ...{decrAlias: 'decr1'}})
}
}
</script>

<style scoped>
</style>

测试

访问: ​​http://localhost:8080/#/compA​​

mapActions

简介

在组件中使用 this.$store.dispatch('xxx') 分发 action,或者使用 mapActions 辅助函数将组件的 methods 映射为 store.dispatch 调用。

import { mapActions } from 'vuex'

export default {
// ...
methods: {
...mapActions([
'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`

// `mapActions` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
]),
...mapActions({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
})
}
}

改写“公共代码”

store/CounterStore.js

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);
const couterStore = new Vuex.Store(
{
state: {
count1: 0
},
mutations: {
incr1(state) {
state.count1++;
},
decr1(state) {
state.count1--;
},
},
actions: {
incr1Async(context) {
setTimeout(() => {
context.commit('incr1')
}, 1000)
},
decr1Async(context) {
setTimeout(() => {
context.commit('decr1')
}, 1000)
}
}
}
);

export default couterStore;

components/ChildOne.vue

<template>
<div class="childOne">
<h1>childOne</h1>
<button @click="incr1">增加:兄弟组件(ChildTwo)</button>
<button @click="decr1">减少:兄弟组件(ChildTwo)</button>
<button @click="incr1Async">异步增加:兄弟组件(ChildTwo)</button>
<button @click="decr1Async">异步减少:兄弟组件(ChildTwo)</button>
</div>
</template>

<script>
import {mapActions} from 'vuex'
export default {
data() {
return {
}
},
methods: {
incr1() {
this.$store.commit('incr1');
},
decr1() {
this.$store.commit('decr1');
},
...mapActions(['incr1Async', 'decr1Async']),
}
}
</script>

<style scoped>
</style>


举报

相关推荐

0 条评论