使用vuex集中管理状态

  • Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化 
  • // store.js
    
    /*
    vuex的核心管理对象模块:store
     */
    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
    // 状态对象
    const state = { // 初始化状态 这里放置的状态可以被多个组件共享
      count: 1,
      name: 'daming'
    }
    const mutations = {}
    const action = {}
    const getters = {}
    
    export default new Vuex.Store({
      state, // 状态
      mutations, // 包含多个更新state函数的对象
      actions, // 包含多个队形事件回调函数的对象
      getters // 包含多个getter计算属性函数的对象
    })
    
    
    // main.js
    
    /*
    入口JS
     */
    import Vue from 'vue'
    import App from './App.vue'
    import store from './store'
    
    // 创建vm
    /* eslint-disable no-new */
    new Vue({
      el: '#app',
      components: {App}, // 映射组件标签
      template: '<App/>', // 指定需要渲染到页面的模板
      store // 所有的组件对象都多了一个属性:$store
    })
    

    在组件中获取vuex状态

    虽然将所有的状态放入Vuex,会使状态变化更显式和易调试,但也会使代码变得冗长和不直观。如果有些状态严格属于单个组件,最好还是作为组件的局部状态,比如temp变量,tempcount,tempcount2作为组件的局部状态。

  • <!-- App.vue -->
    
    <template>
      <div id="example">
        {{count}}
        {{name}}
        {{nameAlias}}
      </div>
    </template>
    
    <script>
    import { mapState } from 'vuex'   // 引入mapState
    export default {
      data () {
        return {
          // 使用 Vuex 并不意味着你需要将所有的状态放入 Vuex。虽然将所有的状态放到 Vuex 会使状态变化更显式和易调试,但也会使代码变得冗长和不直观。
          // 如果有些状态严格属于单个组件,最好还是作为组件的局部状态。你应该根据你的应用开发需要进行权衡和确定。
          // 下面的temp变量,tempcount,tempcount2作为组件的局部状态
          temp: 'hello',
          tempcount: 1,
          tempcount2: 2
        }
      },
      computed: {
          // tempCountPlusTempCount2 这个计算属性并没有涉及到vuex管理的状态
          tempCountPlusTempCount2() { 
              return this.tempcount+this.tempcount2
          } 
          
          // 由于 Vuex 的状态存储是响应式的,所以可以使用计算属性来获得某个状态
          // 当状态改变时,都会重新求取计算属性,并且触发更新相关联的 DOM
          // 通过下面的计算属性,就可以在当前组件中访问到count,name,nameAlias等了 在模板中我们通过大括号符号打印出来
          
          // 下面的计算属性涉及到了vuex管理的状态
          
    	  count () { // 这实际上是ES6中对象的简化写法 完整写法是 count: function { return this.$store.state.count }
              return this.$store.state.age
          },
          name () { // 这实际上是ES6中对象的简化写法 完整写法是 name: function { return this.$store.state.age }
              return this.$store.state.age
          },
          nameAlias () {
            return this.$store.state.name
          }
          countplustempcount: function (state) {
            return this.tempcount + this.$store.state.count
          },
          countplustempcount2 (state) {
            return this.tempcount2 + this.$store.state.count
          } 
          
          // 但有一个问题
          // 当一个组件需要获取多个状态的时候,将这些状态都声明为计算属性会有些重复和冗余。比如上面的name(),count(),nameAlias(),显得重复,代码冗长
          // 为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性,让你少按几次键:
      }
    }
    </script>
    

    但有一个问题,当一个组件需要获取多个状态的时候,将这些状态都声明为计算属性会有些重复和冗余。比如上面的name(),count(),nameAlias(),显得重复,代码冗长。为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性,让你少按几次键

  • mapState接收一个对象

    mapState函数的可以接受一个对象Object<string | function>。对象中可以包含字符串或函数。mapState()函数的返回结果是一个对象。

  • <template>
      <div id="example">
        {{count}}
        {{name}}
        {{nameAlias}}
      </div>
    </template>
    
    <script>
    import { mapState } from 'vuex'
    export default {
      data () {
        return {
          temp: 'hello',
          tempcount: 1,
          tempcount2: 2
        }
      },
      computed: mapState({
        count: 'count',  // string    映射 this.count 为 store.state.count的值
        // 箭头函数可使代码更简练
        name: (state) => state.name, // function   映射 this.name 为 store.state.name的值
        nameAlias: 'name', // string   映射 this.nameAlias 为 store.state.name的值
        countplustempcount: function (state) { // 用普通函数this指向vue实例,但是在箭头函数中this就不是指向vue实例了,所以这里必须用普通哈数
          return this.tempcount + state.count
        },
        countplustempcount2 (state) {
          return this.tempcount2 + state.count
        }   
      })
    }
    </script>
    

  • 我们继续看上面的mapState函数
  • computed: mapState({
        count: 'count',  // string    映射 this.count 为 store.state.count的值
        // 箭头函数可使代码更简练
        name: (state) => state.name, // function   映射 this.name 为 store.state.name的值
        nameAlias: 'name', // string   映射 this.nameAlias 为 store.state.name的值
        countplustempcount: function (state) { // 用普通函数this指向vue实例,但是在箭头函数中this就不是指向vue实例了,所以这里必须用普通哈数
          return this.tempcount + state.count
        },
        countplustempcount2 (state) {
          return this.tempcount2 + state.count
        } 
    })
    

    上面mapState()函数接收了一个对象。
    对象的第一个属性是string类型的,count: 'count', 这条语句映射出了this.count, 值等于store.state.count的值。

    对象的第二个属性是一个箭头函数,name: (state) => state.name,,映射 this.name 为 store.state.name的值。

    对象的第三个属性是一个string类型,nameAlias: 'name',映射 this.nameAlias 为 store.state.name的值, 和第一个属性的用法本质是一致的,不过这里映射出的计算属性的名称与 state 的子节点名称不同。

    对象的第四个属性是一个普通函数,普通函数和箭头函数的不同之处在于,普通函数中的this指向了vue实例,因为可以访问到当前组件的局部状态,比如this.tempcount。

    对象的第五个属性是一个普通函数,第五个和第四个的用法本质是一样的,只不过第五个用了ES6中对象的简化写法。

    上面的mapState函数的返回值是一个对象,我们可以看作是这样的
     

    computed:
    { // 这个对象就是mapState的返回值
        count () {
           return this.$store.state.count
        },
        name () {
            return this.$store.state.name
        }
        nameAlias () {
            return this.$store.state.name
        }
        countplustempcount: function (state) {
          return this.tempcount + this.$store.state.count
        },
        countplustempcount2 (state) {
          return this.tempcount2 + this.$store.state.count
        } 
    }
    

    把这个对象赋值给computed不就和原始的写法一样了吗,所以mapState起到了简化的作用。但是我们可以发现比起直接给computed赋值,这里少了tempCountPlusTempCount2这个计算属性。tempCountPlusTempCount2不是有vuex状态计算而来的,是根据组件内的局部状态计算来的。

  • mapState函数结合对象的扩展运算符运算符使用
    对象的扩展运算符(...)用于取出参数对象的所有可遍历属性,拷贝到当前对象之中。为什么要用扩展运算符呢,我们观察到上面直接将mapState函数的返回值赋给computed对象的话,那么computed中就只有对vuex状态的获取,而没有了当前组件的局部状态,比如tempCountPlusTempCount2就没地方放了,所以我们用扩展运算符。

  • let z = { a: 3, b: 4 };
    let n = { ...z }; // 对象的扩展运算符(...)用于取出参数对象的所有可遍历属性,拷贝到当前对象之中
    n // { a: 3, b: 4 }

    所以利用扩展运算符将下面mapState函数的返回值对象

    computed:{
        ...mapState({
            count: 'count',  // string    映射 this.count 为 store.state.count的值
            // 箭头函数可使代码更简练
            name: (state) => state.name, // function   映射 this.name 为 store.state.name的值
            nameAlias: 'name', // string   映射 this.nameAlias 为 store.state.name的值
            countplustempcount: function (state) { // 用普通函数this指向vue实例,但是在箭头函数中this就不是指向vue实例了,所以这里必须用普通哈数
              return this.tempcount + state.count
            },
            countplustempcount2 (state) {
              return this.tempcount2 + state.count
            } 
        })
    }
    

    上面的结果

    computed:{
    	count () {
           return this.$store.state.count
        },
        name () {
            return this.$store.state.name
        }
        nameAlias () {
            return this.$store.state.name
        }
        countplustempcount: function (state) {
          return this.tempcount + this.$store.state.count
        },
        countplustempcount2 (state) {
          return this.tempcount2 + this.$store.state.count
        } 
    }
    

    于是可以将组将内的计算属性和获取vuex状态的计算属性写在一起了。

    computed:{
        tempCountPlusTempCount2() { 
              return this.tempcount+this.tempcount2
        }, 
        ...mapState({
            count: 'count',  // string    映射 this.count 为 store.state.count的值
            // 箭头函数可使代码更简练
            name: (state) => state.name, // function   映射 this.name 为 store.state.name的值
            nameAlias: 'name', // string   映射 this.nameAlias 为 store.state.name的值
            countplustempcount: function (state) { // 用普通函数this指向vue实例,但是在箭头函数中this就不是指向vue实例了,所以这里必须用普通哈数
              return this.tempcount + state.count
            },
            countplustempcount2 (state) {
              return this.tempcount2 + state.count
            } 
        })
    }
    

    这就是mapState的基本用法。

  • mapState函数接受一个数组

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

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

    上面的写法可以看作

    computed: {
        count () {
           return this.$store.state.count
        },
        name () {
            return this.$store.state.name
        }
    }

    最终版的mapState

    computed: {
        tempCountPlusTempCount2() { 
              return this.tempcount+this.tempcount2
        }, 
        ...mapState(['count','name']),
        ...mapState({
            nameAlias: 'name', // string   映射 this.nameAlias 为 store.state.name的值
            countplustempcount: function (state) { // 用普通函数this指向vue实例,但是在箭头函数中this就不是指向vue实例了,所以这里必须用普通哈数
              return this.tempcount + state.count
            },
            countplustempcount2 (state) {
              return this.tempcount2 + state.count
            } 
        })
    }
    


    ————————————————
    版权声明:本文为CSDN博主「夏阳满山2333」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/chenjie9230/article/details/108883055

Logo

前往低代码交流专区

更多推荐