温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

使用Vuex怎么实现模块化

发布时间:2021-03-24 15:56:07 来源:亿速云 阅读:276 作者:Leah 栏目:web开发

这篇文章给大家介绍使用Vuex怎么实现模块化,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

1 文件结构

文件结构的话,模块化的使用要多一个 modules 的文件夹,里面放着细分模块的 js 文件/模块名文件夹。

这里官方的标准是一个模块一个 js 文件,但是要是模块太复杂的话,也可以把里面的代码拆分出来。

// store 文件夹 
│ actions.js
│ getters.js
│ index.js
│ mutations.js
│ state.js
│
└─modules
  │ moduleB.js
  │
  └─moduleA
      index.js
      mutation.js
      state.js

然后在创建 store 的 js 文件中引入这些模块,直接

import moduleA from './modules/moduleA/index'
import moduleB from './modules/moduleB';

export default new Vuex.Store({
  state,
  getters,
  mutations,
  actions,
  modules: {
    moduleA,
    moduleB,
  }
});

2 模块的局部状态对象的定义

模块内部的 getter,mutation 和 action,他们方法接收的参数会和根状态的不一样,我们一个一个来

getter

getter 的话,他会有三个参数,第一个是模块内的 state,第二个是 模块内的 getters,第三个是根节点状态 rootState,

const getters = {
 bFullName: (state, getters, rootState) => `full${state.bName}`
}

mutation

mutation 里面的回调函数传入的第一个参数也是 模块内的 state,其他和根状态定义的时候一样

const mutations = {
 // 这里的 `state` 对象是模块的局部状态
 SET_B_NAME(state, payload) {
  debugger
  state.bName = payload.name;
 }
}

action

最后的 action 的话,他传入还是只有 context 对象,然后咧,这个对象里面的 state 属性指模块内的状态,rootState 指根状态,如下

const actions = {
 ASYNC_SET_NAME({ state, commit, rootState }, payload) {
  setTimeout(() => {
   state.bName = 'asyncName'
  }, 4000)
 }
}

3 使用

3.1 state 获取

这个的话要在原来状态名前面加一个模块名才能放到到模块内的对象。具体如下

// 原先的基础上加个模块名
this.$store.state.moduleB.bName;
// 辅助函数也一样,name 前面加个模块名 Deno
...mapState({
  name: state => state.moduleB.bName,
})

3.2 命名空间

getter,mutation,action 他们默认都是注册在全局命名空间的,所以我们默认是可以和使用根状态一样去使用他们,但是这样不可避免会出现命名冲突的问题,所以使模块有更高的封装性与复用性,我们可以通过添加 `
namespaced: true` 使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。

// moduleB 模块导出的时候加个 namespaced: true,
export default {
 namespaced: true,
 state,
 getters,
 mutations,
 actions,
}

3.2.1 辅助函数的使用

因为有了命名空间这么一层封装,所以我们在用辅助函数的时候都要多加那么一层模块名,具体看下面代码。

// getter
this.$store.getters['moduleB/bFullName']; 

...mapGetters({
 bGetter2: 'moduleB/bFullName'
})

// mutation 
this.$store.commit('moduleB/SET_B_NAME', {
 name: 'QQ'
});

...mapMutations({
 setBname: 'moduleB/SET_B_NAME'
}),

// action
this.$store.dispatch('moduleB/ASYNC_SET_NAME', { name: "JJ" });

...mapActions({
 aSetAge: 'moduleB/ASYNC_SET_NAME',
}),

每次都要写模块名,这样写下来很烦,所以这些辅助函数给我们提供了一个参数位来绑定命名空间。

// moduleB 模块内的 bName
...mapState('moduleB', {
 name: state => state.bName
})

// 同理 mapAction mapMutation 也可以这个样子
...mapAction('moduleB',[
 '/ASYNC_SET_NAME'
])

除了这个之外,如果你当前组件用的 vuex 状态都是一个模块的话,我们可以使用 createNamespacedHelpers 创建基于某个命名空间辅助函数,如下:

import { createNamespacedHelpers } from 'vuex'

const { mapState, mapActions } = createNamespacedHelpers('moduleB') // moduleName

这样创建之后,我们就可以用之前的写法来访问到模块的状态。

...mapState({
 bName: state => state.bName,
}),

3.2.2 在带命名空间的模块内访问全局内容

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

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

modules: {
 foo: {
  namespaced: true,

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

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

    dispatch('someOtherAction') // -> 'foo/someOtherAction' 模块内的 action
    dispatch('someOtherAction', null, { root: true }) // ->'someOtherAction' 全局的 action 

    commit('someMutation') // -> 'foo/someMutation' 模块内的 action
    commit('someMutation', null, { root: true }) // -> 'someMutation' 全局 mutation
   },
   someOtherAction (ctx, payload) { ... }
  }
 }
}

3.2.3 将模块内的 action 注册为全局

这个感觉和维护模块的封装性有点冲突,但是既然作者提出来了,那就学吧,当我们想要我们模块内的某个 action 提升为全局 action 的时候,在他声明的时候,添加 root: true,并将 action 的定义放到 hanler 函数中,具体如下:

const actions = {
  // 模块内 action
  [ASET_AGE]({ commit }, payload) {
    setTimeout(() => {
      commit('SET_B_NAME', payload.name);
    }, 2000)
  },
  // 提升到全局的 action 
  globalAction: {
    root: true,
    handler({ commit }, payload) {
      debugger
      setTimeout(() => {
        commit('SET_B_NAME', payload.name);
      }, 2000)
    }
  }
}

关于使用Vuex怎么实现模块化就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI