zoukankan      html  css  js  c++  java
  • Vuex之state、mapState、...mapState、getters、mapGetters、...mapGetters

    我在项目中发现如下代码:

    computed: {
      ...mapGetters([
        'permission_routes',
        'sidebar'
      ]),
      activeMenu() {
        const route = this.$route
        const { meta, path } = route
        if (meta.activeMenu) {
          return meta.activeMenu
        }
        return path
      },
    }

    其中,...mapGetters是什么语法呢?我查询资料进行了解,它是Vuex的语法。

    然后我了解到Vuex的几个概念,state,mapState和...mapState。

    一、State

    vuex的state和vue的data有很多相似之处,都是用于存储一些数据或者说状态值。这些值将实现被挂载数据和dom的双向绑定,也就是当你改变值的时候可以触发dom的更新。

    state在使用的时候一般被挂载到子组件的computed计算属性上,这样有利于state的值发生改变的时候及时响应给子组件。

    let state = {
      count: 1,
      name: 'lyh',
      sex: '男',
      from: 'china'
    }
    export default state
    <template>
      <div id="example">
        <button @click="decrement">-</button>
        {{count}}
        {{dataCount}}
        <button @click="increment">+</button>
      </div>
    </template>
    <script>
    export default {
      data () {
        return {
          dataCount: this.$store.state.count //用data接收
        }
      },
      computed:{
        count(){
          return this.$store.state.count //用computed接收
        }
      }
      methods: {
        increment () {
          this.$store.commit('increment')
        },
        decrement () {
          this.$store.commit('decrement')
        }
      }
    }
    </script>

    结果为用data接收的值不能及时响应更新,用computed就可以。

    二、mapState

    mapState是state的语法糖。

    在使用mapState之前,要导入这个辅助函数。

    import { mapState } from 'vuex'

    使用方式为

    <template>
      <div id="example">
        <button @click="decrement">-</button>
        {{count}}
        {{dataCount}}
        <button @click="increment">+</button>
        <div>{{sex}}</div>
        <div>{{from}}</div>
        <div>{{myCmpted}}</div>
      </div>
    </template>
    <script>
    import { mapState } from 'vuex'
    export default {
      data () {
        return {
          str: '国籍',
          dataCount: this.$store.state.count
        }
      },
      computed: mapState({
        count: 'count', // 第一种写法
        sex: (state) => state.sex, // 第二种写法
        from: function (state) { // 用普通函数this指向vue实例,要注意
          return this.str + ':' + state.from
        },
        // 注意下面的写法看起来和上面相同,事实上箭头函数的this指针并没有指向vue实例,因此不要滥用箭头函数
        // from: (state) => this.str + ':' + state.from
        myCmpted: function () {
          // 这里不需要state,测试一下computed的原有用法
          return '测试' + this.str
        }
      }),
      methods: {
        increment () {
          this.$store.commit('increment')
        },
        decrement () {
          this.$store.commit('decrement')
        }
      },
      created () {
        // 写个定时器,发现computed依旧保持了只要内部有相关属性发生改变(不管是当前实例data中的改变,还是vuex中的值改变)都会触发dom和值更新
        setTimeout(() => {
          this.str = '国家'
        }, 1000)
      }
    }
    </script>

    在使用的时候,computed接收mapState函数的返回值,你可以用三种方式去接收store中的值,具体可以看注释。

    事实上第二种和第三种是同一种,只是前者用了ES6的偷懒语法——箭头函数,在偷懒的时候要注意一个问题,this指针的指向问题。

    我们不要在vue中为了偷懒使用箭头函数,会导致很多很难察觉的错误,如果你在用到state的同时还需要借助当前vue实例的this,请务必使用常规写法。

    当然computed不会因为引入mapState辅助函数而失去原有的功能——用于扩展当前vue的data,只是写法会有一些奇怪。

    如果你已经写了一大堆的computed计算属性,做了一半发现你要引入vuex,还想使用mapState辅助函数的方便,你可以做下列事情。

    //之前的computed
    computed:{
        fn1(){ return ...},
        fn2(){ return ...},
        fn3(){ return ...}
        ........
    }
    //引入mapState辅助函数之后
     
    computed:mapState({
        //先复制粘贴
        fn1(){ return ...},
        fn2(){ return ...},
        fn3(){ return ...}
        ......
        //再维护vuex
        count:'count'
        .......
    })

    我们希望我们可以不用去做一些复制粘贴的无用操作,而是直接使用mapState,希望它能自动融入到当前生产环境中。

    ES6+(或者说ES7)提供了这个方便。

    三、...mapState

    事实上...mapState并不是mapState的扩展,而是...对象展开符的扩展。

    这样,我们就可以自由的使用mapState了。

    //之前的computed
    computed:{
        fn1(){ return ...},
        fn2(){ return ...},
        fn3(){ return ...}
        ........
    }
    //引入mapState辅助函数之后
     
    computed:{
        //原来的继续保留
        fn1(){ return ...},
        fn2(){ return ...},
        fn3(){ return ...}
        ......
        //再维护vuex
        ...mapState({  //这里的...不是省略号了,是对象扩展符
            count:'count'
        })
    }

    学习了state,mapState和...mapState之后,我们可以继续学习getters,mapGetters,...mapGetters这几个概念。

    四、getters

    Vuex提供了state这样的状态统一管理树,你可以在vue中用computed计算属性接收这些公共状态以便使用,当然你也可以在接收原值的基础上对这个值做出一些改造,如

    computed:{
      sex:function(){
          return this.$store.state.sex + '加个字符串,算是改造'    
      }
    }

    但是如果你的其他组件也要使用这种改造方式去改造这个值,那你可能不得不去复制粘贴这个函数到别的组件中。

    当然为了解决这个问题,vuex本身就提供了类似于计算属性的方式,getters可以让你从store的state中派生出一些新的状态。

    当然如果不是多个组件要用到这个状态,或者说每个子组件用到的派生属性不一样,那么你完全可以不用getters。

    //state.js
    let state = {
      from: 'china',
      arr: [2, 3, 1, 4, 6]
    }
    export default state
    // getters.js
    // 第一个参数是state
    let address = (state) => {
      return '国籍:' + state.from
    }
    // 第二个参数可以访问getters
    let addressMore = (state, getters) => {
      return '其他描述' + getters.address
    }
    // return 一个function,这个function可以传参,当然这个function最后会返回一个具体的数值
    //本例中这个方法用于查询state中的arr数组是否存在某个值
    let findArr = (state) => (number) => {
      let ifExit = state.arr.find((n) => n === number) // arr.find是ES6语法中数组的扩展
      if (typeof (ifExit) === 'undefined') {
        return false
      } else {
        return true
      }
    }
    export {address, addressMore, findArr}
    <template>
      <div>
        <div>{{from}}</div>
        <div>{{from2}}</div>
      </div>
    </template>
     
    <script>
    // import { mapGetters } from 'vuex'
    export default {
      computed: {
        from: function () {
          return this.$store.getters.address
        },
        from2: function () {
          return this.$store.getters.addressMore
        }
      },
      created () {
        console.log(this.$store.getters.findArr(2))
        console.log(this.$store.getters.findArr(7))
      }
    }
    </script>

    结果为:

    五、mapGetters辅助函数

    与mapState类似,可辅助理解。

    <template>
      <div>
        <div>{{from}}</div>
        <div>{{from2}}</div>
      </div>
    </template>
     
    <script>
    import { mapGetters } from 'vuex'
    export default {
      computed:  mapGetters({
          'from': 'address',
          'from2': 'addressMore',
          'find': 'findArr'
      }),
      created () {
        console.log(this.find(1)) // 由于getters已经通过computed挂载到当前实例,所以你不需要再通过this.$store.getters的方法去访问
        console.log(this.$store.getters.findArr(2))
        console.log(this.$store.getters.findArr(7))
      }
    }
    </script>

    六、...mapGetters

    <template>
      <div>
        <div>{{from}}</div>
        <div>{{from2}}</div>
      </div>
    </template>
     
    <script>
    import { mapGetters } from 'vuex'
    export default {
      computed:  {
        ...mapGetters({
          'from': 'address',
          'from2': 'addressMore',
          'find': 'findArr'
        })
      },
      created () {
        console.log(this.find(1)) // 由于getters已经通过computed挂载到当前实例,所以你不需要再通过this.$store.getters的方法去访问
        console.log(this.$store.getters.findArr(2))
        console.log(this.$store.getters.findArr(7))
      }
    }
    </script>

    很多情况下是用不到getters的,请按需使用,不要用getters去管理state的所有派生状态,如果有多个子组件或者说子页面要用到,才考虑用getters。

  • 相关阅读:
    Nodejs----基本数据类型
    VUE----整理
    Linux----知识储备
    Linux----常用操作
    GIT-常用操作
    CAS 4.0 配置开发手册(转)
    cas配置全攻略(转)
    cas sso入门(转)
    cas sso原理(转)
    spring web flow 2.0入门(转)
  • 原文地址:https://www.cnblogs.com/luoyihao/p/14739061.html
Copyright © 2011-2022 走看看