美文网首页
Vuex状态管理模式

Vuex状态管理模式

作者: gitJason | 来源:发表于2021-06-16 14:21 被阅读0次

    Vuex是什么?

    Vuex是一个专为Vue.js应用程序开发的状态管理模式
    Vuex是全局的状态管理

    Vuex用来做什么?

    Vuex用于组件之间的传值,多个组件共享数据
    Vuex的数据是响应式的,当我们在A组件更新了某个状态,来到B组件,B组件会动态更新

    State

    State用来存储状态

    在组件中获取Vuex状态

    由于Vuex的状态存储是响应式的,从store实例中读取状态最简单的方法就是在计算属性中返回某个状态:

    computed: {
      count: () => store.state.count
      // or 将状态从根组件“注入”到每一个子组件中 Vue.use(Vuex)
      count: () => this.$store.state.count
    },
    

    mapState 获取方式

    import { mapState } form 'vuex'
    
    computed: {
        ...mapState({
            // 1. 基础用法 store/index.js
            isLogin: (state) => state.isLogin
            // 2. 使用模块 store/modules/user.js
            isLogin: (state) => state.user.isLogin
        }),
    },
    

    Getters

    Getters类似计算属性,只有当它的依赖发生改时才会重新求值

    Getter 接受 state 作为其第一个参数:

    const store = new Vuex.Store({
      state: {
        todos: [
          { id: 1, text: '...', done: true },
          { id: 2, text: '...', done: false }
        ]
      },
      getters: {
        doneTodos: state => {
          return state.todos.filter(todo => todo.done)
        }
      }
    })
    

    在组件中使用

    computed: {
      doneTodosCount () {
        return this.$store.getters.doneTodosCount
      }
    }
    

    mapGetters 获取方式

    import { mapGetters } from 'vuex'
    
    export default {
      // ...
      computed: {
        // 使用对象展开运算符将 getter 混入 computed 对象中
        ...mapGetters([
          'doneTodosCount',
          'anotherGetter',
          // ...
        ])
        // 使用Modules store/user.js
        ...mapGetters('user',[
          'increment',
          'incrementBy',
          // ...
        ])
      }
    }
    

    Mutations

    更改store中状态的唯一方法是mutations

    mutations第一个参数是state

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

    调用方法

    store.commit('increment')
    

    你可以向store.commit传入额外的参数

    // ...
    mutations: {
      increment (state, n) {
        state.count += n
      }
    }
    
    store.commit('increment', 10)
    

    记住 Mutation 必须是同步函数

    在组件中提交 Mutation

    computed: {
      doneTodosCount () {
        return this.$store.commit('increment')
      }
    }
    

    mapMutations 方式提交

    import { mapMutations  } from 'vuex'
    
    export default {
      // ...
      methods: {
        // 使用对象展开运算符将 getter 混入 computed 对象中
        ...mapMutations([
          'increment',
          'incrementBy',
          // ...
        ])
        // 使用Modules store/user.js
        ...mapMutations('user',[
          'increment',
          'incrementBy',
          // ...
        ])
      }
    }
    

    Action

    Action 类似于 mutation,不同在于:

    • Action 提交的是 mutation,而不是直接变更状态。
    • Action 可以包含任意异步操作。

    注册一个简单的 action:

    const store = new Vuex.Store({
      state: {
        count: 0
      },
      mutations: {
        increment (state) {
          state.count++
        }
      },
      actions: {
        increment (context) {
          context.commit('increment')
        }
      }
    })
    

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

    实践中,我们会经常用到 ES2015 的 参数解构 (opens new window)来简化代码

    actions: {
      increment ({ commit }) {
        commit('increment')
      }
    }
    

    在组件中触发 Action

    methods: {
      increment () {
        this.$store.dispatch('increment')
      }
    }
    

    mapActions 方式触发

    import { mapActions  } from 'vuex'
    
    export default {
      // ...
      methods: {
        // 使用对象展开运算符将 getter 混入 computed 对象中
        ...mapActions([
          'increment',
          'incrementBy',
          // ...
        ])
        // 使用Modules store/user.js
        ...mapActions('user',[
          'increment',
          'incrementBy',
          // ...
        ])
      }
    }
    

    组合 Action

    有时候需要组合多个action,例如有时候需要在actionB中调用actionA

    actions: {
      actionA ({ commit }) {
        return new Promise((resolve, reject) => {
          setTimeout(() => {
            commit('someMutation')
            resolve()
          }, 1000)
        })
      }
    }
    

    利用 async / await ,我们可以如下组合 action:

    actions: {
      actionA ({ commit }) {
        return new Promise((resolve, reject) => {
          setTimeout(() => {
            commit('someMutation')
            resolve()
          }, 1000)
        })
      }
      async actionB ({ dispatch, commit }) {
        await dispatch('actionA') // 等待 actionA 完成
        // ...
      }
    }
    

    Modules

    当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
    modules 将 store 分割成模块。
    每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块。

    const moduleA = {
      state: () => ({ ... }),
      mutations: { ... },
      actions: { ... },
      getters: { ... }
    }
    
    const moduleB = {
      state: () => ({ ... }),
      mutations: { ... },
      actions: { ... }
    }
    
    const store = new Vuex.Store({
      modules: {
        moduleA,
        moduleB
      }
    })
    

    项目使用案例

    @/store/modules/user.js :

    export default {
        namespaced: true,
        state: {
            // 存储状态
            isLogin: false
        },
        mutations: {
            // 修改状态
            SET_ISLOGIN(state, val) {
                state.isLogin = val
            }
        },
        actions: {
            // 异步操作
            login({ commit }, query) {
                api.login({
                    code: query.code,
                    iv: query.iv
                }).then(res => {
                    commit('SET_ISLOGIN', true)
                })
            }
        }
    }
    

    @/store/index.js :

    import Vue from 'vue'
    import Vuex from 'vuex'
    import user from './modules/user'
    
    // 安装 Vuex
    Vue.use(Vuex)
    
    // 创建一个 store
    export default new Vuex.Store({
      modules: {
        user,
        // ...
      }
    })
    

    @/main.js :

    import Vue from 'vue';
    import App from './App.vue';
    import router from './router';
    import store from '@/store';
    
    new Vue({
        router,
        store,
        render: h => h(App)
    }).$mount('#app');
    

    相关文章

      网友评论

          本文标题:Vuex状态管理模式

          本文链接:https://www.haomeiwen.com/subject/lpoxyltx.html