Vuex实践(下)-mapState和mapGetters

做者:小土豆biubiubiujavascript

博客园:www.cnblogs.com/HouJiao/html

掘金:https://juejin.im/user/58c61b4361ff4b005d9e894d前端

简书:https://www.jianshu.com/u/cb1c3884e6d5vue

微信公众号:土豆妈的碎碎念(扫码关注,一块儿吸猫,一块儿听故事,一块儿学习前端技术)java

码字不易,点赞鼓励哟~es6

  

  Vuex系列文章web

    《Vuex实践(上)》vuex

    Vuex实践(中)-多module中的state、mutations、actions和getters数组

    《Vuex实践(下)-mapState和mapGetters》浏览器

  

一.前言

  本文章是vuex系列的最后一篇,主要总结的是如何使用mapState和mapGetters访问vuex中的state和getters。

二.多个模块中mapState和mapGetters的使用

  上一篇文章《Vuex实践(中)》里面咱们总结的就是多模块的内容,因此关于store.js、moduleA.js和moduleB.js的代码保持不变。

  在此为了方便观看,我将这三个文件的代码在贴在这里

E:\MyStudy\test\VueDemo\src\vuex\store.js

 1 import Vue from 'vue'
 2 import Vuex from 'vuex'
 3 import moduleA from './moduleA'
 4 import moduleB from './moduleB'
 5 
 6 Vue.use(Vuex)  7 
 8 export default new Vuex.Store({  9  state: { 10         counter: 1000
11  }, 12  mutations: { 13         //递增
14  increase(state) { 15             console.log("store-increase") 16             state.counter++
17  }, 18         //递减
19  decrement(state) { 20             state.counter--
21  } 22  }, 23  actions: { 24  increaseAction(context) { 25             setTimeout(function(){ 26                 //action经过提交mutation改变共享数据状态
27                 context.commit('increase'); 28             },3000) 29  }, 30  decrementAction(context){ 31             setTimeout(function(){ 32                 //action经过提交mutation改变共享数据状态
33                 context.commit('decrement'); 34             },3000) 35  } 36  }, 37  getters: { 38  doubleCounter(state) { 39             return state.counter*state.counter 40  } 41  }, 42  modules: { 43  a: moduleA, 44  b: moduleB 45  } 46 })

 

E:\MyStudy\test\VueDemo\src\vuex\moduleA.js

const moduleA = { namespaced: true, state:{ counter: 100 }, mutations: { //递增
 increase(state) { console.log("moduleA-increase") state.counter++ }, //递减
 decrement(state) { state.counter-- } }, actions: { increaseAction(context) { setTimeout(function(){ //action经过提交mutation改变共享数据状态
                context.commit('increase'); },3000) }, decrementAction(context){ setTimeout(function(){ //action经过提交mutation改变共享数据状态
                context.commit('decrement'); },3000) } }, getters: { doubleCounter(state) { return state.counter*state.counter } } } export default moduleA

 

E:\MyStudy\test\VueDemo\src\vuex\moduleB.js

 1 const moduleB = {  2     namespaced: true,  3  state:{  4         counter: 5
 5  },  6  mutations: {  7         //递增
 8  increase(state) {  9             console.log("moduleB-increase") 10             state.counter++
11  }, 12         //递减
13  decrementAction(state) { 14             state.counter--
15  } 16  }, 17  actions: { 18  increaseAction(context) { 19             setTimeout(function(){ 20                 //action经过提交mutation改变共享数据状态
21                 context.commit('increase'); 22             },3000) 23  }, 24  decrementAction(context){ 25             setTimeout(function(){ 26                 //action经过提交mutation改变共享数据状态
27                 context.commit('decrement'); 28             },3000) 29  } 30  }, 31  getters: { 32  doubleCounter(state){ 33             return state.counter*state.counter 34  } 35  } 36 } 37 
38 export default moduleB

 

  如今须要在组件中使用mapState和mapGetters

  仍是按照以前的套路

  在App.vue组件中访问根根模块store和a模块moduleA的state和getters。

  在Index.vue组件中访问b模块moduleB的state和getters

1.使用mapState

  使用mapState访问state的写法也有多种,咱们一个一个来实践(不包含es6的写法)

  [第一种写法]

E:\MyStudy\test\VueDemo\src\App.vue  

<template>
  <div id="app">
    <img src="./assets/logo.png">
    <!-- 获取共享数据 -->
    <h1>这里是App组件</h1>
    <h3> App组件获取共享数据 </h3>
    <h3>使用mapState访问根组件counter : {{counter}}</h3>
    <h3>使用mapState访问a组件counter : {{counterA}}</h3>
    <hr/>
    <Index></Index>
  </div>
</template>

<script> import Index from './components/Index' import { mapState } from 'vuex' export default { name: 'App', components: { Index }, computed: mapState({ //访问store根模块
 counter: function(state){ return state.counter }, //访问a模块
 counterA: function(state){ return state.a.counter } }) } </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>

 

E:\MyStudy\test\VueDemo\src\components\Index.vue

<template>
    <div>  
        <h1>这里是Index.vue组件</h1>
        <h3>Index组件获取共享数据 </h3>
        <h3>使用mapState访问b模块counter :{{ counterB }}</h3>
    </div>
</template>
<script> import { mapState } from 'vuex' export default { name: 'Index', computed: mapState({ counterB: function(state){ return state.b.counter } }) } </script>

 

  在App.vue、Index.vue组件中使用mapState,首先第一步须要引入mapState

  接着就是在计算属性computed中使用,以Index.vue中的代码为例

computed: mapState({
    counterB: function(state){
         return state.b.counter
    }
})

     能够看到mapState关联到vue的计算属性中。

  获取b模块的state,只须要以vue计算属性的形式在函数中返回state.b.counter便可。

  (获取根模块state返回state.counter;获取a模块state返回state.a.counter)

  这样在模板中就可使用计算属性的语法访问state

  备注:这种方式,当注释掉命名空间的配置后,依然能够正常访问到不一样模块的state

  [第二种写法]

  第二种写法和第一种有些相似,只是以字符串的形式返回计算属性。

  咱们先在Index.vue组件中访问b模块的数据。

E:\MyStudy\test\VueDemo\src\components\Index.vue

 1 <template>
 2     <div>  
 3         <h1>这里是Index.vue组件</h1>
 4         <h3>Index组件获取共享数据 </h3>
 5         <h3>使用mapState访问b模块counter :{{ counterB }}</h3>
 6     </div>
 7 </template>
 8 <script>
 9 import { mapState } from 'vuex'
10 export default { 11  name: 'Index', 12  computed: mapState('b',{ 13  counterB: 'counter'
14  }) 15 } 16 </script>

  核心代码以下

computed: mapState('b',{
    counterB: 'counter'
})

    能够看到,mapState第一个参数限定了模块名称。

  接着就是以'counter'字符串的形式返回了b模块的counter值。

  那么根据以前一系列的总结,可知

    访问根模块的数据,不须要限定第一个参数;

    访问a模块的数据,须要限定第一个参数为a

  然而,由于访问根模块和访问a模块同在App.vue组件中,那么由于mapState第一个参数限定的问题,咱们须要编写两个mapState。

  如今直接上代码(只把computed中的核心代码贴上)

E:\MyStudy\test\VueDemo\src\App.vue  

computed: { ...mapState({ //访问store根模块
      counter: 'counter', }), ...mapState('a',{ //访问a模块
      counterA: 'counter' }) }

  能够看到,我写了两个mapState,仍是...mapState的形式。

  ...mapState它是ES6中扩展运算符的语法,应用在mapState上,官方文档是这样说的

  

   (

    此处若对此有疑问,能够在去仔细研究一下对象扩展运算符的内容。

    我这里贴一个简单的示例

    

      最终newObj的打印结果为  

    相信这个示例能够很清楚的解释咱们写的两个...mapState的写法

  )

  官方文档处提到这个对象展开运算符的场景是为了将一个组件中本来的计算属性和mapState混合使用

  (混合使用这个点平常开发会用到,很实用的一个点)

  那本次咱们也是使用这个语法成功的获取到了不一样模块的state。

 

  最后咱们在使用浏览器查看一下最终App.vue和Index.vue中的结果

  

  咱们已经使用mapState成功的访问到了多模块中的state数据。

 

  备注:这种关于mapState的写法不能删除moduleA和moduleB中关于命令空间的配置,不然会报错。

  最后做者还尝试了一个问题,就是将moduleA.js中的state属性改成counterA

  

  而后修改了App.vue组件中computed访问a模块数据的代码

  

  最后发现这样并不能正常访问到a模块的state数据。(删除a模块的命名空间配置也没法正常访问)

  这个尝试仅给你们一个反面的示例。

2.使用mapGetters

  前面使用mapState访问了state数据,那么如今咱们使用mapGetters访问一下vuex中的getters。

  在研究以后发现,暂时发现使用mapGetters访问一下vuex中的getters只有字符串的形式。

E:\MyStudy\test\VueDemo\src\App.vue

 1 <template>
 2   <div id="app">
 3     <img src="./assets/logo.png">
 4     <!-- 获取共享数据 -->
 5     <h1>这里是App组件</h1>
 6     <h3> App组件获取共享数据 </h3>
 7     <h3>使用mapState访问根组件counter : {{counter}}</h3>
 8     <h3>使用mapState访问a组件counter : {{counterA}}</h3>
 9     <h3>使用mapGetters访问根组件doubleCounter : {{doubleCounter}}</h3>
10     <h3>使用mapGetters访问a组件doubleCounter : {{doubleCounterA}}</h3>
11     <hr/>
12     <Index></Index>
13   </div>
14 </template>
15 
16 <script>
17 import Index from './components/Index'
18 import { mapState,mapGetters } from 'vuex'
19 export default { 20  name: 'App', 21  components: { Index }, 22  computed: { 23  ...mapState({ 24       //访问store根模块
25  counter: 'counter', 26  }), 27  ...mapState('a',{ 28       //访问a模块
29  counterA: 'counter'
30  }), 31  ...mapGetters({ 32       //访问store根模块
33  doubleCounter: 'doubleCounter'
34  }), 35  ...mapGetters('a',{ 36       //访问store根模块
37  doubleCounterA: 'doubleCounter'
38  }) 39 
40  } 41   
42 } 43 </script>
44 
45 <style>
46 #app {
47  font-family: 'Avenir', Helvetica, Arial, sans-serif;
48  -webkit-font-smoothing: antialiased;
49  -moz-osx-font-smoothing: grayscale;
50  text-align: center;
51  color: #2c3e50;
52  margin-top: 60px;
53 }
54 </style>

 

E:\MyStudy\test\VueDemo\src\components\Index.vue

 1 <template>
 2     <div>  
 3         <h1>这里是Index.vue组件</h1>
 4         <h3>Index组件获取共享数据 </h3>
 5         <h3>使用mapState访问b模块counter :{{ counterB }}</h3>
 6         <h3>使用mapGetters访问b组件doubleCounter : {{doubleCounterB}}</h3>
 7     </div>
 8 </template>
 9 <script>
10 import { mapState,mapGetters } from 'vuex'
11 export default { 12  name: 'Index', 13  computed: { 14  ...mapState('b',{ 15  counterB: 'counter'
16  }), 17  ...mapGetters('b',{ 18  doubleCounterB: 'doubleCounter'
19  }), 20  } 21 } 22 </script>

 

  浏览器查看结果

  

三.总结

  到此本篇文章基本已经结束了,vuex系列的三篇文章也已经结束。

  关于vuex中大多数的用法基本已经覆盖到,可是还有一些内容没有覆盖到。

  后期攒够一篇在继续更新

  在最后呢,再补充一点,无论是mapState和mapGetters,咱们给传入的都是一个字典。

  简单一些的,假如咱们的state和getters不重名,咱们能够给mapState和mapGetters传入一个数组

1 mapState([ 2      'counterA','counterB',... 3 ]) 4 
5 mapGetters([ 6      'dobuleCounterA','dobuleCounterB',... 7 ])

  这样数组中的字符串元素会直接去映射对应的state和getters。

  (字典形式至关因而将state和getters中的名称在映射过程当中进行重命名)


  

原文出处:https://www.cnblogs.com/HouJiao/p/12186237.html