• vuex中modules的使用


    modules提出的目的:

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

    (来自vuex文档)

    模块化思想在做项目较大的时候十分有用,下面依据vuex文档简单记录一下modules的使用方式

    如何使用modules

    const moduleA = {
      state: { ... },//局部state
      mutations: { ... },
      actions: { ... },
      getters: { ... }
    }
    
    const moduleB = {
      state: { ... },//局部state
      mutations: { ... },
      actions: { ... }
    }
    
    const store = new Vuex.Store({
    state:{ ... },//全局state modules: { a: moduleA, b: moduleB } })

     1.其中moduleA和modulesB的state为局部state,而store对象建立时与modules同级的为全局state

      访问moduleA中的state :store.state.a,  全局state :store.state

    2.对于moduleA和moduleB的getters和mutations中,对于参数与全局的getters和mutations存在一定区别

      getters和mutations中第一个参数的state为局部state,

      getters的第二个参数为全局getters,第三个为根state(rootState)

    3.对于moduleA和moduleB的和mutations中

    局部state通过context.state,全局state通过content.rootState ,全局getters通过rootGetters

    actions: {
        test({ state, rootState }) {
          ....
        }

    4.moduleA和moduleB除了state为局部,其他stategetters和mutations,actions可以全局直接使用,但参数的作用域全局的存在不同

    module 的命名空间

    什么是命名空间,就是在module中添加一个属性,namespaced: true, 就完成了,而命的名字就是在全局中导入的module的名字,

    如上边代码中moduleA对应的a为其名字。

    • 注意:module中state不受命名空间影响,本身就是局部state的
    • 而getters和mutations,actions在命名后为局部,不能直接在全局调用

    代码来自vuex文档

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

     在命名空间里面你要是想访问全局的getters,mutations和actions的话,需要注意一些

    getters存在四个参数,state(局部), getters(局部), rootState(全局), rootGetters(全局)

    例子

    getters: {
          // 在这个模块的 getter 中,`getters` 被局部化了
          // 你可以使用 getter 的第四个参数来调用 `rootGetters`
          someGetter (state, getters, rootState, rootGetters) {
            getters.someOtherGetter // -> 'foo/someOtherGetter'
            rootGetters.someOtherGetter // -> 'someOtherGetter'
          },
          someOtherGetter: state => { ... }
        },
    

     对于mutation,不存在rootState可以访问全局state

    对于action,存在rootState和rootGetters

    接下来一个问题,因为命名空间,commit和dispatch都局部化,所以如何使用全局的commit和dispatch呢

    答案是:通过传入{root:true}作为第三个参数打开路径调用全局的commit和dispatch

    直接上例子

    actions: {
          // 在这个模块中, dispatch 和 commit 也被局部化了
          // 他们可以接受 `root` 属性以访问根 dispatch 或 commit
          someAction ({ dispatch, commit, getters, rootGetters }) {
            dispatch('someOtherAction') // -> 'foo/someOtherAction'
            dispatch('someOtherAction', null, { root: true }) // -> 'someOtherAction'
    
            commit('someMutation') // -> 'foo/someMutation'
            commit('someMutation', null, { root: true }) // -> 'someMutation'
          },
    

    如果你想在module中注册一个全局的actions,可以通过如下方式,

    在actions中添加一个属性(action函数名字),通过对象方式,添加root为true的属性以及在handle中添加action方法{root:true,handle(){...}}

    actions: {
            someAction: {
              root: true,
              handler (namespacedContext, payload) { ... } // -> 'someAction'
            }
          }
    

    接下来是如何将命名空间与语法糖(mapState,mapMutations,mapGetters,mapActions)结合起来

    ...mapState({
        a: state => state.moduleA.a,
        b: state => state.moduleB.b
      })
    ...mapGeters({
    a:"moduleA/a"
    })


    ...mapActions([‘moduleA/foo’]) =>使用为 this[moduleA/foo]()
    ...mapMutations([‘moduleA/foo’])=>使用为 this[moduleA/foo]()

     如上所见,简单直白

    关于上边为什么mapState和mapGetters为什么要采用这种方式,起一个别名a,由于不起别名a,如何采用同Action和Mutation一样的写法的话

    emm,那么使用为this['moduleA/a'],但是在template使用模板语法的时候表示为{{this['moduleA/a']}}得不出想要的数据,所以采用别名

    获取另一种写法

    ...mapState(“moduleA”,["a"])
    ...mapGetters("moduleA",["a"] ...mapActions("moduleA",[‘foo’]) =>使用为 this.foo() ...mapMutations("moduleA",[‘foo’]) =>使用为 this.foo()

    如果你觉得需要些指定命名的路径比较麻烦,你可以调用createNamespacedHelpers这个创建某个命名空间的辅助函数

    import { createNamespacedHelpers } from 'vuex'
    
    const { mapState, mapActions } = createNamespacedHelpers('moduleA')

    ...mapState({
        a: state => state.a,
        b: state => state.b
      })
    
    ...mapActions([‘foo’]) =>使用为 this.foo()
    ...mapMutations([‘foo’]) =>使用为 this.foo()

  • 相关阅读:
    WPF
    WPF RadioButton 转换
    JS框架之收集专帖
    WPF用ShowDialog()弹出窗体时控制该窗体的显示位置,并传值回父窗体
    WPF学习笔记:MVVM模式下,ViewModel如何关闭View?
    Microsoft Visual Studio 下载转帖
    RelayCommand命令
    动态调用webservice,不需要添加Web References
    你会在C#的类库中添加web service引用吗?
    Quartz Cron 触发器 Cron Expression 的格式
  • 原文地址:https://www.cnblogs.com/kongbaifeiye/p/12577941.html
Copyright © 2020-2023  润新知