方便的组件api
为了避免每次都需要通过this.$store来调用api,vuex提供了mapState、mapMutations、mapGetters mapActions、createNamespacedHelpers 等api,
可以很方便的在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
| <template> <div class="cart"> <h2>Your Cart</h2> <p v-show="!products.length"><i>Please add some products to cart.</i></p> <ul> <li v-for="product in products" :key="product.id"> {{ product.title }} - {{ product.price | currency }} x {{ product.quantity }} </li> </ul> <p>Total: {{ total | currency }}</p> <p><button :disabled="!products.length" @click="checkout(products)">Checkout</button></p> <p v-show="checkoutStatus">Checkout {{ checkoutStatus }}.</p> </div> </template>
<script> import { mapGetters, mapState } from 'vuex'
export default { computed: { //这里使用mapState ...mapState({ checkoutStatus: state => state.cart.checkoutStatus }), //这里使用了mapGetters ...mapGetters('cart', { products: 'cartProducts', total: 'cartTotalPrice' }) }, methods: { checkout (products) { this.$store.dispatch('cart/checkout', products) } } } </script>
|
以上是vuex官方示例shopping-cart中一个组件(examples/shopping-cart/components/ShoppingCart.vue)。同样的,我们还能这样使用mapActions和mapMutations。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <script> import { mapActions mapMutations } from 'vuex'
export default { //... methods: { //这里使用了mapActions ...mapActions('cart', [ 'addProductToCart' ]), //这里使用了mapMutations ...mapMutations({ decrement: 'decrementProductInventory' }) } //... } </script>
|
组件api实现解析
这几个组件api放在helpers.js文件中,我们先来看看mapState函数的源码。
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
| //normalizeNamespace是进行参数处理,如果存在namespace便加上命名空间 export const mapState = normalizeNamespace((namespace, states) => { const res = {} //normalizeMap是对传入的states进行处理,也就是数据格式的统一 normalizeMap(states).forEach(({ key, val }) => { //遍历,对参数里的所有state都包裹一层函数,最后返回一个对象 res[key] = function mappedState () { let state = this.$store.state let getters = this.$store.getters if (namespace) { //如果存在namespace,取该namespace下module的state和getters const module = getModuleByNamespace(this.$store, 'mapState', namespace) if (!module) { return } state = module.context.state getters = module.context.getters } //val是函数,把state和getters传递进去 return typeof val === 'function' ? val.call(this, state, getters) : state[val] } // mark vuex getter for devtools res[key].vuex = true }) return res })
|
这里我们回顾一下上面mapState的用法:
1 2 3 4 5 6 7 8 9 10
| import { mapState } from 'vuex' export default { computed: { //这里使用mapState ...mapState({ checkoutStatus: state => state.cart.checkoutStatus }) } /** 省略 **/ }
|
经过 mapState 函数处理后的结果:
1 2 3 4 5 6 7 8 9
| import { mapState } from 'vuex' export default { computed: { checkoutStatus() { return this.$store.state.cart.checkoutStatus } } /** 省略 **/ }
|
对比上面的mapState的用例和经过mapState函数处理后的结果,就可以很清楚的知道mapState函数就是在每个state包装一下,使原本需要在this.$store上取state的写法
变成 state => stat.cart 的写法而已。
同样的我们再来对比下mapGetters的写法和处理结果
1 2 3 4 5 6 7 8 9 10 11 12 13
| //使用mapGetters的写法 import { mapGetters } from 'vuex'
export default { computed: { //这里使用了mapGetters ...mapGetters('cart', { products: 'cartProducts', total: 'cartTotalPrice' }) }, /** 省略 **/ }
|
1 2 3 4 5 6 7 8 9 10 11 12
| //mapGetters处理后的结果 export default { computed: { products() { return this.$store.getters['cart']['cartProducts'] }, total() { return this.$store.getters['cart']['cartTotalPrice'] } } /** 省略 **/ }
|
好,现在是彻底明白了,mapState、mapGetters函数其实就相当于一种语法糖,将原本需要this.$store来获取数据的写法变成另外一种更加简易的写法。
mapActions、mapMutations的功能大同小异,这里就不再赘写了。
小结
本节主要就讲mapState、mapMutations、mapGetters、mapActions这几个函数功能的实现,当然还有其他一些辅助函数或工具函数就留下自己去看吧。
到此,vuex的源码解析就结束吧。不难,我们再整理下要点: