zoukankan      html  css  js  c++  java
  • 状态管理Vuex的使用总结

    1、Vuex.store 的基本使用

    Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

    Vuex 使用单一状态树,即用一个对象包含全部的应用层级状态,这也意味着,每个应用将仅仅包含一个 store 实例。

    每一个 Vuex 应用的核心就是 store(仓库)。Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们更方便地使用一些工具比如 devtools 来调试我们的应用。

    1.1、创建 store

    • 首先安装 Vue、Vuex,在一个 JS 文件中创建一个 store
    //store.js
    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex);
    
    const store = new Vuex.Store({
      state: {
        count: 0
      },
      getters: {
        age () {
          return 232
        }
      },
      actions: {},
      mutations: {
        increment(state,) {
          state.count++;
        }
      }
    })
    
    export default store;
    • 然后在 main.js 中引入 store
    // main.js
    import Vue from 'vue'
    import App from './App'
    import router from './router'
    import store from './store/store.js'
    
    Vue.config.productionTip = false
    
    new Vue({
      el: '#app',
      router,
      store,
      components: { App },
      template: '<App/>'
    })

    通过 store 选项能将状态从根组件“注入”到每一个子组件中(前面需先调用 Vue.use(Vuex))

    在 main.js 文件中引入 store 后,该 store 实例会注入到根组件下的所有子组件中,其他组件就可以通过 this.$store 来访问这个 store 仓库了。

    通过 this.$store.state 来访问数据、通过 this.$store.getters 来访问 getters 数据、通过 this.$store.commit('') 来调用 mutations 变更状态,通过调用 this.$store.dispatch('') 来触发 actions 调用 mutations。

    2、Vuex.Store 的选项

    2.1、state 选项

    在组件中使用 store 中的 state,我们可以直接通过 this.$store.state 来使用,也可以通过将状态返回到组件中的计算属性中来使用,而且每当 $store.state.count 变化的时候, 都会重新求取计算属性。

    2.1.1、mapState() 函数

    我们可以使用 mapState 辅助函数来帮助我们将 state 返回到组件的计算属性中,减少我们的代码量。

    mapState(nameSpace, Array | Object),mapState 辅助函数的第一个参数可选,表示的是一个命名空间字符串(跟模块化有关),第二个参数可以是数组或者对象。函数最终返回一个对象,我们可以使用对象展开运算符将此对象插入到计算属性中。

    import { mapState } from 'vuex'
    
    <script>
    export default {
      data () {
        return {}
      },
      computed: {
         name () { return 'wen' },
    
         ...mapState([
            'count' // 组件中的 this.count 则是 this.$store.state.count
         ])
      }
    }
    </script>
    
    // 或者使用对象作为参数
    computed: {
        ...mapState({
          count: state => state.count,
    
          // 传字符串参数 'count' 等同于 `state => state.count`
          countAlias: 'count',
    
          // 为了能够使用 `this` 获取局部状态,必须使用常规函数
          countPlusLocalState (state) {
            return state.count + this.localCount
          }
      })
    }

    2.2、getters 选项

    store 中的 getters 就像计算属性一样,getters 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

    Getter 接受 state 作为其第一个参数,Getter 也可以接受其他 getter 作为第二个参数。

    const store = new Vuex.Store({
      state: {
        age: 23
      },
      getters: {
       //接收一个参数
        myAge: state => {
          return state.age + 2
        },
        //接收两个参数
        myAge2: (state, getters) => {
            return getters.myAge + 2;
        }
      }
    })

    在组件中可以通过 this.$store.getters 来访问 getters 中的数据。

    你也可以通过让 getter 返回一个函数,来实现给 getter 传参。注意,getter 在通过方法访问时,每次都会去进行调用,而不会缓存结果

    getters: {
      // 返回一个函数
      getTodoById: (state) => (id) => {
        return state.todos.find(todo => todo.id === id)
      }
    }
    
    //组件中访问时通过函数的形式访问,传入参数
    this.$store.getters.getTodoById(2)

    2.2.1、mapGetters() 函数

    类似于 mapState 辅助函数一样,可以通过 mapGetters 辅助函数将 store 中的 getter 映射到局部计算属性

    import { mapGetters } from 'vuex'
    
    export default {
      computed: {
        // 数组作为参数
        ...mapGetters([
          'doneTodosCount',
          'anotherGetter',
          // ...
        ])
      }
    }
    
    //对象作为参数
    ...mapGetters({
      // 把 `this.doneCount` 映射为`this.$store.getters.doneTodosCount`
      doneCount: 'doneTodosCount'
    })

    2.3、mutations 选项

    更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。mutation 必须是同步函数,即里面不能有异步的操作。要想异步操作,可以使用 actions。

    mutation 接受 state 作为第一个参数。

    const store = new Vuex.Store({
      state: {
        count: 1
      },
      mutations: {
        increment (state) {
          // 变更状态
          state.count++
        }
      }
    })

    在组件中通过 this.$store.commit('increment') 的形式来调用 mutation 

    mutation 可以接收其他数据作为其他参数,即载荷(payload)。一般来说,其他的参数可以作为对象传过去,这样更加简洁一点。

    mutations: {
      increment (state, n) {
        state.count += n
      }
    }
    //调用时
    this.$store.commit('increment', 10)
    
    // payload 是对象
    mutations: {
      increment (state, payload) {
        state.count += payload.amount
      }
    }
    //调用时
    store.commit('increment', {
      amount: 10
    })
    //或者此时可以使用对象风格进行提交
    store.commit({
      type: 'increment',
      amount: 10
    })

    2.3.1、mutation 往 state 的某个对象中添加属性

    当 mutation 需要在 state 中的某个对象添加新属性时,不能直接添加,应该使用 Vue.set 方法,比如 Vue.set(obj, 'newProp', 123) 。或者是新生成一个对象,用新对象替换旧对象:state.obj = { ...state.obj, newProp: 123 }

    state: {
       man: {
           name: 'wen'
       }
    },
    mutations: {
       //添加属性
       addProp (state) {
           Vue.set(state.man, 'age', 22)   // 或者:state.man = Object.assgin({}, state.man, {age: 22})
       }
    }

    2.3.2、mapMutations() 函数

    mapMutations() 辅助函数将 store 中的 mutations 映射到局部方法中。

    import { mapMutations } from 'vuex'
    
    export default {
      methods: {
        ...mapMutations([
          'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`
    
          // `mapMutations` 也支持载荷:
          'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
        ]),
    ...mapMutations({ add:
    'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')` }) } }

    2.4、actions 选项

    Action 用来提交 mutation,由 mutation 来变更状态,Action 可以包含任意异步操作。

    Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。

    const store = new Vuex.Store({
      state: {
        count: 0
      },
      mutations: {
        increment (state) {
          state.count++
        }
      },
      actions: {
        increment (context) {
          context.commit('increment')
        }
    
        // 下面的写法更加简洁
        increment ({ commit }) {
             commit('increment')
        }
      }
    })

    在组件内可以通过 this.$store.dispatch('') 来触发 action。

    actions 可以接收额外的参数,额外的参数写成一个对象更加简洁。

    //接收额外的参数
    actions: {
      increment ({ commit }, n) {
        if(n >= 0){
            commit('increment')
       }
      }
    }
    
    //用对象作为额外的参数
    actions: {
      increment ({ commit }, payload) {
        if(payload.n >= 0){
            commit('increment')
       }
      }
    }
    //此时的调用方式
    this.$store.dispatch('increment', {
      amount: 10
    })
    
    // 以对象形式分发
    store.dispatch({
      type: 'incrementAsync',
      amount: 10
    })

    2.4.1、mapActions() 函数

    可以使用 mapActions 辅助函数将 actions 映射到组件的 methods 中。

    import { mapActions } from 'vuex'
    
    export default {
      methods: {
        ...mapActions([
          'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`
    
          // `mapActions` 也支持载荷:
          'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
        ]),
        ...mapActions({
          add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
        })
      }
    }

    2.4.2、组合使用多个 action 

    我们可以组合多个 action以处理比较复杂的异步流程。

    如果 action 中有异步操作,我们可以使用 promise或者 async/await 函数来更改状态。

    也可以通过返回一个 promise来组合使用action,store.dispatch 可以处理 action 处理函数返回的 Promise,并且 store.dispatch 仍旧返回 Promise,由此我们可以在 store.dispatch() 后面接着写我们需要的操作。

    actions: {
      actionA ({ commit }) {
        return new Promise((resolve, reject) => {
          setTimeout(() => {
            commit('someMutation')
            resolve()
          }, 1000)
        })
      }
      
      //在另一个 action 中可以操作前面的 action 函数 resolve 出的数据
      actionB ({ dispatch, commit }) {
        return dispatch('actionA').then(() => {
          commit('someOtherMutation')
        })
      }
    }
    
    //在组件中
    store.dispatch('actionA').then(() => {
    })

    在 action 中使用 async/await 

    // 下面假设 getData() 和 getOtherData() 返回的是 Promise
    actions: {
      async actionA ({ commit }) {
        commit('gotData', await getData())
      },
      async actionB ({ dispatch, commit }) {
        await dispatch('actionA') // 等待 actionA 完成
        commit('gotOtherData', await getOtherData())
      }
    }
  • 相关阅读:
    .net 调用命令行进行解压缩
    《jQuery实战》第1章 引荐JQuery
    将指定URL文件下载到指定服务器
    Oracle学习笔记
    Spring3 AOP的使用
    Field类使用以及getDeclaredFields方法
    spring 3的使用
    Json数据类型
    RotateAnimation详解
    GsonJava对象生成Json串
  • 原文地址:https://www.cnblogs.com/wenxuehai/p/11362855.html
Copyright © 2011-2022 走看看