辅助函数

mapState , mapGetters, mapMutations, mapActions

state

在vue的任何组件中都可以使用this.$store.state.属性名访问
在开发中我们推荐将store中的state赋值给需要使用该状态的组件的计算属性中(一定不能把state赋值给data,state发生改变时不会重新给data赋值)

如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
export default {
    data() {
        return {
// 错误state.book 发生改变时book不会更新
            myBookthis.$store.state.book
        }
    },
    computed: {
        book() {
// 正确 state.book会作为当前计算属性的依赖,当state.book发生改变时计算属性book将会重新计算当前值
            return this.$store.state.book
        }
    }
}

mapState

Vuex 为了简化 state与计算属性配合使用时的代码,提供了一个辅助函数mapState 可以简化上面的写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
    <div>{{book}}</div>
</template>

<script>
// 首先引入辅助函数mapState
import {mapState} from 'vuex'

export default {
    /*
    computed: {
        book() {
return this.$store.state.book;
},
    }*/

// 下面的写法等价于上面的写法
    computed: {
...mapState(['book'])
}
}
</script>

Getters

getter就是Vuex的计算属性,开发人员可以将state 或其他getter 计算后的的返回值存放在指定getter中,当前getter会将这些依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算
在任何组件中都可以通过this.$store.getter.属性名访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// src/store/index.js

export default new Vuex.Store({
state: {
score: [30, 20, 80, 10, 9, 66],
},
getters: {
// 可以认为是 store 的计算属性, 就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
calcScore(state) {
// p(state, getters, rootState, rootGetters)
//state: 当前模块的state
//getters: 当前模块的getters
//rootState: 全局的state
//rootGetters: 全局的getters
let ps = state.score.filter(v => {
return v >= 30;
})
return ps.join('-');
}
},
})

mapGetters

  • mapState可以接收一个字符串数组作为参数,数组中的每一项字符串都会成为当前组件的计算属性并且与Vuex中的同名getter建立映射对应关系。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    <template>
        <div>{{calcScore}}</div>
    </template>

    <script>
    // 首先引入辅助函数mapGetters
    import {mapGetters} from 'vuex'

    export default {
        /*
        computed: {
            book() {
    return this.$store.getters.calcScore;
    },
        }*/

    // 下面的写法等价于上面的写法
        computed: {
    ...mapGetters(["calcScore"])
    }
    }
    </script>
  • mapGetters可以接收对象作为参数,对象的每一个key都会成为当前组件的计算属性名,value必须是一个字符串并且与Vuex中的同名getter建立映射对应关系。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <template>
       <div>{{s1}}</div>
    </template>

    <script>
    import {mapGetters} from 'vuex'
    export default {
        computed: {
            ...mapGetters({
                s1'calcScore'
            })
        }
    }
    </script>

Mutations

vuex规定mutation是唯一可以修改state的地方

1
2
3
4
5
6
7
8
9
10
11
export default new Vuex.Store({
state: {
book: 'HTML+CSS',
},
mutations: { // 修改state的方法
// 同步操作 直接修改
changeBook(state, book) {
state.book = book;
},
},
})

mutation

在Vuex中,mutation函数的第一个参数是state,
这是Vuex自动传递的,因此在调用mutation函数时不需要显式传递state。
Vuex会自动将当前的状态对象作为第一个参数传递给mutation函数。

mapMutations

注意: Mutation 需遵守 Vue 的响应规则 Vuex 的 store 中的状态是响应式的,那么当我们变更状态时,监视状态的 Vue 组件也会自动更新。这也意味着 Vuex 中的 mutation 也需要与使用 Vue 一样遵守一些注意事项:
1、最好提前在你的 store 中初始化好所有所需state属性。
2、当需要在对象上添加新属性时,你应该使用 Vue.set(obj, ‘newProp’, 123), 或者以新对象替换老对象
Vue.set(obj, ‘newProp’, 123)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { mapMutations } from 'vuex'

//将mutation里的函数映射到组件里
...mapMutations([ //使用es6的拓展运算符
'INCREASE_SHOPCART',
'DECREASE_SHOPCART'
])

//将mutation里的函数映射到组件里,在组件里
this.INCREASE_SHOPCART === this.$store.commit('INCREASE_SHOPCART') //true

//在有参数的情况下,mutation的state默认参数可以省略
this.INCREASE_SHOPCART(id) === this.$store.commit('INCREASE_SHOPCART',id) //true


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

Actions

Vuex给开发人员提供了一个可以执行异步操作的函数action

注意: action函数中接收两个参数
参数一 context 与 store对象相似所以可以访问 context.state / context.getters / context.commit / context.dispatch
参数二 action的载荷,action载荷与mutation一样只有一个如果需要传递多个参数请传递对象
action是不允许直接修改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
36
37
38
39
// 在Vuex中通过配置选项actions创建,并使用 $store.dispatch方法分发action

// 1、在应用中通过store.dispatch('action名',载荷)的形式调用
import Vue from 'vue'
import Vuex from 'vuex'
import * as types from './mutation-types'

Vue.use(Vuex)

export default new Vuex.Store({
    state: {
        result: {}
    },
    mutations: {
        [types.SET_RESULT](state, result) {
            // 修改state
            state.result = result
        }
    },
    actions: {
        searchMusic(context, keywords) {
            console.log(context)
            fetch('http://musicapi.leanapp.cn/search?keywords=' + keywords)
            .then(res => res.json())
            // 只有mutation才能修改state,所以action异步请求数据后,只能通过提交mutation修改state
            .then(({result}) => context.commit(types.SET_RESULT, result))
        }
    }
})


// vue.js
<script>
export default {
created() {
this.$store.dispatch('searchMusic', '海阔天空')
}
};
</script>

mapActions

mapActions生成的方法只接受一个参数,这个参数就是当前action的载荷。

  • 方法一: mapActions可以接收一个字符串数组作为参数,数组中的每一项字符串都会成为当前组件的方法并且与Vuex中的同名action建立映射对应关系。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <script>
    import {mapActions} from 'vuex'

    export default {
      created() {
        //   this.$store.dispatch('searchMusic','海阔天空')
        this.searchMusic('海阔天空')
      },
      methodsmapActions(['searchMusic']),
    };
    </script>
  • 方法二: mapAction可以接收对象作为参数,对象的每一个key都会成为当前组件的方法名,value必须是action的同名字符串与Vuex中的action建立映射对应关系。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <script>
    import {mapState, mapActions} from 'vuex'

    export default {
      created() {
        //   this.$store.dispatch('searchMusic','海阔天空')
        this.search('海阔天空')
      },
      methodsmapActions({search'searchMusic'}),
    };
    </script>

总结

应用层级的状态都应该集中在store中
提交 mutation 是更改状态state的唯一方式,并且这个过程是同步的。
异步的操作应该都放在action里面

参 考

vuex参考链接
vuex模块化