1.准备

为了说明这个问题,我们来一起实现一个小需求
即 现在有两个module - productuser
需求为调用 product 模块的方法 去修改 user 模块的 userInfo(用户名信息)

// module user 模块
const user = {
	state: {
		userInfo: '鸣人', // 用户信息
	},
	mutations:{
		SET_UserInfo(state,payload) {
			state.userInfo = payload.userInfo
		},
	},
	actions: {
		setuserInfo(context,payload) {
			return new Promise(resolve => {
				context.commit('SET_UserInfo',payload)
				resolve();
			})
		},
	}
}

export default user

不难看出, 上述需求 其实就是在 product 模块的方法中的去调用 user模块 的 setuserInfo 方法

那我们来看看 product 模块

const product = {
	actions: {
		callsetuserInfo(context,payload) {
                // 在这里调用 user 模块的 setuserInfo 方法
		},
	}
}

export default product

接着就是注册这两个模块:

import Vue from 'vue'
//引用Vuex
import Vuex from 'vuex'
Vue.use(Vuex)

import product from '@/store/modules/product'
import user from '@/store/modules/user'
// import  getters from '@/store/modules/getters.js'
// import  actions from '@/store/modules/actions.js'



//实例store对象
const store = new Vuex.Store({
	modules: {
		product,
		user
		// getters,
		// actions
	}
})

//导出store对象
export default store

2.跨模块调用state

这里我们首先要了解 方法中的第一个参数 context
打印一下
在这里插入图片描述

发现有 commit,dispatch,getters,rootGetters,rootState 几个参数

结合官网说明:

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

即: context.state -> 访问的是 当前模块下的 state
context.rootState -> 是根节点状态

const product = {
	actions: {
		callsetuserInfo(context,payload) {                
                // 通过 根节点状态 去访问 user 模块的 userInfo信息
                console.log(context.rootState.user.userInfo)  // '鸣人'
		},
	}
}

export default product

在这里插入图片描述

跨模块调用getter

和跨模块调用state类似 ,通过 context.rootGetters去访问模块

namespaced情况区分

跨模块调用mutation,action
这里要区分 模块是否开启了命名空间 namespaced
首先来看默认情况 (没有开启namespaced)

官网说明:

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

跨模块调用actions:

// 三个参数: 1. 模块/方法名 2.参数 3.是否从跟节点寻找
context.dispatch('需要调用的方法名',params,{root: true})

跨模块调用mutations:

// 三个参数: 1. 模块/方法名 2.参数 3.是否从跟节点寻找
context.commit('需要调用的方法名',params,{root: true})
const product = {
	actions: {
		callsetuserInfo(context,payload) {
                  // 因为是默认为全局注册  可以直接访问 setuserInfo  
                  //  {root: true} 表明从根节点寻找  如果不加 则是从当前模块中
                  //  这里即 product模块 去找 setuserInfo 方法 (当然找不到)
           		contxt.dispatch('setuserInfo',{
				userInfo: '宇智波佐助'
			},{root: true})
		},
	}
}
export default product

在页面中调用:

...mapState({
    cartList: state => state.product.cartList,
    userInfo:state => state.user.userInfo,
}),
methods: {
    // 因为为默认情况,Action全局注册,这里使用辅助函数直接取值
 ...mapActions( [
   'callsetuserInfo',
 ]),

async onLoad(params) {
    this.callsetuserInfo().then(()=> {
        // 打印user 模块 的 userInfo
        console.log(this.userInfo) //  宇智波佐助 
    })
}

打印设置值- 宇智波佐助 ,默认情况(未开启命名空间)跨模块调用actions 成功
跨模块调用mutations类似,语法糖改为 context.commit 即可
在这里插入图片描述

开启命名空间的情况:

官方文档:

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

const store = createStore({
  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']
          }
        }
      }
    }
  }
})

官网中的 在带命名空间的模块内访问全局内容 的例子:

modules: {
  foo: {
    namespaced: true,

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

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

        dispatch('someOtherAction') // -> 'foo/someOtherAction'
        dispatch('someOtherAction', null, { root: true }) // -> 'someOtherAction'

        commit('someMutation') // -> 'foo/someMutation'
        commit('someMutation', null, { root: true }) // -> 'someMutation'
      },
      someOtherAction (ctx, payload) { ... }
    }
  }
}

好了,了解之后 。回到我们的需求 = =!
模块user,product 先 开启命名空间 如下:

const user = {
	namespaced: true,
     // 后续代码
 }

在product模块 中去调用user 模块的action方法

const product = {
	actions: {
		callsetuserInfo(context,payload) {
                  // 因为开启了命名空间  访问方法 需要通过模块 user/setuserInfo  
           		context.dispatch('user/setuserInfo',{
				userInfo: '宇智波佐助'
			},{root: true})
		},
	}
}
export default product

在页面中调用

 ...mapState({
    cartList: state => state.product.cartList,
    userInfo:state => state.user.userInfo,
}),
methods: {
    // 因为为开启命名空间  不能直接访问方法
    // 普通写法
   ...mapActions([
   'product/callsetuserInfo',
 ]),  
    // 简化写法:   将模块的空间名称字符串作为第一个参数传递
 ...mapActions('product',[
   'callsetuserInfo',
 ]),
 // 如果想调用多个不同命名空间的方法
  ...mapActions('模块B',[
   '模块B Function',
 ]),
async onLoad(params) {
    this.callsetuserInfo().then(()=> {
        // 打印user 模块 的 userInfo
        console.log(this.userInfo) //  宇智波佐助 
    })
}

参考文档: https://vuex.vuejs.org/zh/guide/modules.html

Logo

前往低代码交流专区

更多推荐