Vuex模块化用法 跨模块调用方法
vuex模块化用法 跨模块调用方法
1.准备
为了说明这个问题,我们来一起实现一个小需求
即 现在有两个module - product 和 user
需求为调用 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) // 宇智波佐助
})
}
更多推荐
所有评论(0)