• vuex (6)


    Module 

    由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时, store对象就有可能变得相当臃肿。

    为了解决以上问题,Vuex允许我们将store分割成模块( module )。 每个模块拥有自己的 state、mutation、 action、 getter  甚至是嵌套子模块——从上至下进行同样方式的分割。

    const moduleA = {
           state: () => ({...}),
           mutations: {...},
           actions: {},
           getters: {}
    }
    
    const moduleB = {
           state: () => ({...}),
           mutations: {...},
           actions: {},
           getters: {}
    }
    
    const store = createStore({
          modules:{
               a:moduleA,
               b:moduleB
          }
    })
    
    store.state.a   //  -> moduleA 的状态
    store.state.b   //  -> moduleB 的状态

    模块的局部状态

     对于模块内部的mutation 和 getter, 接收的第一个参数是模块的局部状态对象。

    const moduleA = {
           state: () => ({
                  count: 0
           }),
    
           mutations: {
                  increment (state){
                        //  这里的 `state` 对象是模块的局部状态
                        state.count++
                  }
           },
    
           getters: {
                 doubleCount (state) {
                       return state.count *2
                 }
           }
    }

    同样, 对于模块内部的action, 局部状态通过 context.state 暴露出来, 根节点状态则为 context.rootState :

    const moduleA = {
      // ...
    
      actions: {
             incrementIfOddOnRootSum ({ state,  commit,  rootState }) {
                    if((state.count + rootState.count) % 2 ===1){
    
                          commit("increment")
                    }
            }
      }
    }

    对于模块内部的 getter ,根节点状态会作为第三个参数暴露出来

    const moduleA = {
         // ...
         getters:{
               sumWithRootCount (state, getters, rootState) {
                      return state.count + rootState.count
               }
         }
    }

    默认情况下,模块内部的 action 和 mutation 仍然是注册在全局命名空间的,这样使得多个模块能够对同一个 action 或 mutation 作出响应。 Getter 同样也默认在全局命名空间,但是目前这并非出于功能上的目的(仅仅是维持现状来避免非兼容性变更)。必须注意,不要再不同的、无命名空间的模块中定义两个相同的 getter 从而导致错误。

    如果希望你的模块具有更高的封装性和复用性,你可以通过添加 namespace:true 的方式 使其成为带命名空间的模块。当模块被注册后,它的所有 getter、 action 及 mutation 都会自动根据模块注册的路径调整命名。例如:

    const store = createStore({
    
          modules: {
    
               account: {
                      namespace:true,
                      
                      // 模块内容 (module assets)
                      state: () => ({...}),  //模块的状态已经是嵌套的了,使用 `namespace` 属性不会对其产生影响
                      
                      getters: {
                           isAdmin () {...}  //  ->getters['account/isAdmin']
                      },
    
                      actions: {
                          login () {...}  //  -> dispatch('account/login')
                      },
    
                      mutations: {
                          login () {...}  //  ->commit('account/login')
                     },
    
                     modules: {
                            myPage: {
                                 state: () => ({...}),
                                 getters: {
                                        profile (){...}   //  ->getters['account/profile']     
                                 }
                            },
    
                            // 进一步嵌套命名空间
                            posts: {
                                  namespace: true,
                                  state: () => ({...}),
                                  getters: {
                                       popular () {...}  // ->getters['account/posts/popular']
                                  }
                            }
                     }
               }
          }
    })

    启用了命名空间的 getter 和 action 会收到局部化的 getter , dispatch 和 commit。换言之,你在使用模块内容(module assets)时不需要在同一模块内额外添加空间名前缀。更改 namespaced 属性后不需要修改模块内的代码。

    在带命名空间的模块内访问全局内容 (Global Assets)

    如果你希望使用全局 state 和 getter, rootState 和 rootGetters 会作为第三和第四参数传入getter,  也会通过context 对象的属性传入 action。

    若需要在全局命名空间内分发 action 或 提交 mutation,将 {root: true} 作为第三参数传给 dispatch 或 commit 即可。

    modules: {
    
          foo: {
                namespace:true,
    
                getters: {
                     // 在这个模块的getter中, `getters`被局部化了
                     // 你可以使用 getter 的第四个参数来调用 `rootGetters`
                     someGetter (state, getters, rootState, rootGetters){
    getters.someOtherGetter
    // ->`foo/someOtherGetter` rootGetters.someOtherGetter // ->someOtherGetter } }, actions: { // 在这个模块中,dispatch 和 commit也被局部化了 // 你可以使用 getter 的第四个参数来调用 `rootGetters` someAction({dispatch, commit, getters, rootGetters}){ getters.someGetter // -> `foo/someGetter`, rootGetters.someGetter // -> `someGetter` dispatch('someOtherAction') // ->'foo/someOtherAction' dispatch('someOtherAction', null, {root:true}) // ->someOtherAction commit('someMutation') // ->`foo/someMutation` commit('someMutation', null, { root:true }) // -> `someMutation` }, someOtherAction(ctx, payload){...} } } }

    在带命名空间的模块注册全局 action 

    若需要在带命名空间的模块注册全局 action, 你可以添加 root: true, 并将这个 action 的定义放在函数 handler 中。

    {
    
      actions: {
    
           someOtherAction ({dispatch}){
              dispatch('someAction')
           }
      },
    
     modules:{
          foo: {
               namespace: true,
    
                actions: {
                      someAction: {
                           root: true,
                           handler (namespaceContext, payload) {...}   //  ->'someAction'
                     }
               }
         }
     }
    
    }

    带命名空间的绑定函数

    当使用 mapState、mapGetters、mapActions 和 mapMutations 这些函数来绑定带命名空间的模块时,写起来可能比较繁琐:

     computed: {
        ...mapState({
               a: state => state.some.nested.module.a
               b: state => state.some.nested.module.b
         })
     },
    
     methods: {
         ...mapActions([
              'some/nested/module/foo',   //  -> this['some/nested/module/foo']()
               'some/nested/module/bar'   //  -> this['some/nested/module/bar']()
        ])
     }

    对于这种情况,你可以将模块的空间名称作为第一个参数传递给上述函数,这样所有绑定都会自动将该模块作为上下文,于是上边的例子可以简化为:

      computed: {
           ...mapState('some/nested/module', {
                  a:state => state.a,
                  b:state => state.b
           })
      },
    
      methods: {
          ...mapActions('some/nested/module', [
                 'foo',  // -> this.foo()
                 'bar'   // -> this.bar()
          ])
      }
  • 相关阅读:
    加密算法 科普文
    《电商后台系统产品逻辑解析》学习笔记
    基于Docker的Consul服务发现集群搭建
    从阿里中台战略看企业IT架构转型之道
    CanalSharp.AspNetCore v0.0.4-支持输出到MongoDB
    领域驱动设计学习之路—DDD的原则与实践
    一个实时收集MySql变更记录的组件CanalSharp.AspNetCore
    基于Jenkins Pipeline的ASP.NET Core持续集成实践
    熊逸《唐诗50讲》感时篇
    一个Mini的ASP.NET Core框架的实现
  • 原文地址:https://www.cnblogs.com/zhishiyv/p/15883559.html
Copyright © 2020-2023  润新知