Vuex详解(二) 进阶——Vuex的模块化使用

随着项目越来越复杂,我们可能向store中添加的状态越来越多,这不便于我们对数据的管理,同时,既然vue是模块化开发,那么我们能否将Vuex中的状态也进行模块化管理呢?

Vuex——Module

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

const moduleA = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态

值得注意的是,这里两份模块的state写法state: () => ({ ... }),这里通过函数来返回了一个state对象。如果我们不这样写,而是使用一个纯对象来声明模块的状态,那么这个状态对象就会通过引用被共享,导致状态动向被修改时store或模块间数据互相污染的问题。实际上,这和Vue组件内的date类似,它也是使用了一个函数。

但是,模块化store对象之后,如果将所有的内容都写在一个store.js中,就显得过于臃肿,我们难以快速定位数据,这时候,我们还可以按照模块将store分成不同的文件。

import defaultState from "./state/defaultState";
import mutationsRoot from "./mutations/mutations.root";
import actionsRoot from "./actions/actions.root";
import gettersRoot from "./getters/getters.root";

import stateModuleA from "./state/state.moduleA";
import mutationsModuleA from "./mutations/mutations.moduleA";
import gettersModuleA from "./getters/getters.moduleA";
import actionsModuleA from "./actions/actions.moduleA";

export default () => {
  return new Vuex.Store({
    state: () => defaultState(),
    mutations: mutationsRoot,
    actions: actionsRoot,
    getters: gettersRoot,
    modules:{
      a: {
        namespaced: true,
        state: stateModuleA(),
        mutations: mutationsModuleA,
        getters: gettersModuleA,
        actions: actionsModuleA
      }
    }
  })
}

所以现在的目录结构为:
在这里插入图片描述

使用模块化Vuex

以下就是store中的a模块:

    modules:{
      // a: {
      //   namespaced: true,
      //   state: () => require('./state/state.moduleA').default(),
      //   mutations: () => import('./mutations/mutations.moduleA'),
      //   getters: () => import('./getters/getters.moduleA'),
      //   actions: () => import('./actions/actions.moduleA')
      // }
      a: {
        namespaced: true,
        state: () => {
          return {
            numA: 10,
            numB: 20
          }
        },
        mutations: {
          updateNum (state, data) {
            state.numA = data.numA
            state.numB = data.numB
          }
        },
        getters: {
          sum(state, getters, rootState){
            return state.numA + state.numB
          }
        },
        actions: {
          updateNumsAsync (store, data) {
            setTimeout(() => {
              store.commit('updateNum', data.nums)
            }, data.time)
          }
        }
      }
    }

app中使用模块中的状态:

<template>
  <div>
    <div>{{numA}} {{numB}}</div>
    <div>{{sum}}</div>
  </div>
</template>
<script>
import {
  mapState,
  mapMutations,
  mapActions,
  mapGetters
} from 'vuex'
export default {
  name: 'app',
  methods:{
    ...mapMutations(["a/updateNums"]),
    ...mapActions(["a/updateNumsAsync"])
  },
  mounted() {
    console.log(this.numA)
    this['a/updateNumsAsync']({
      nums: {
        numA: 50,
        numB: 40
      },
      time: 3000
    })
  },
  computed:{
    ...mapState({
      numA: state => state.a.numA,
      numB: state => state.a.numB
    }),
    ...mapGetters({
      sum: 'a/sum'
    })
  }
}
</script>

注意:

  1. 默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应。如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。也就是说,我们在a模块中定义的updateNum,sum,updateNumsAsync其实是注册在全局命名空间的,但是由于我们设置了namespaced: true,所以注册这些函数时,将其名称由函数名=>模块名称/函数名,即a/updateNum等。
  2. 在使用mapGetters,mapMutations,mapActions来简化代码风格时,我们的函数名发生了改变,所以不能直接使用updateNum,而是应该使用a/updateNum;但是,如果我们使用mapState来简化代码,a模块中的state不能通过a/状态名称(即a/numA)来获取,而是通过numA: state => state.a.numA来获得。如果不使用mapState,我们可以通过this.$store.state.a.numA来获取状态。
  3. 在使用a模块下的函数时,比如...mapGetters({sum: 'a/sum'}),其实我们也可以这样...mapGetters([ 'a/sum' ]),但是,这样写并不便于在模板中使用getter函数。如果在js中,我们可以使用this['a/sum']();来调用getter函数,但是如果我们在模板中,<div>{{a/sum}}</div>,这种写法是无法达到我们的期望的。所以,在使用store模块中的函数时,我们应当先为其设置一个别名,然后通过别名使用它。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue.js是一个流行的JavaScript框架,它允许您构建动态Web应用程序。Vuex是一个专为Vue.js应用程序开发的状态管理模式。它允许您在应用程序中管理和维护状态,例如用户信息、购物车、主题等。Vuex将状态存储在一个集中的存储库中,称为storeVuex的核心概念包括state、mutations、actions和getters。 - state:存储应用程序级别的状态,可以通过store.state访问。 - mutations:用于更改状态的函数,必须是同步函数。可以通过store.commit方法调用。 - actions:用于处理异步操作的函数,可以包含任意异步操作。可以通过store.dispatch方法调用。 - getters:用于从store中获取状态的函数,可以通过store.getters访问。 下面是一个简单的示例,演示如何在Vue.js应用程序中使用Vuex: 1.安装Vuex ```shell npm install vuex --save ``` 2.创建store ```javascript import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state) { state.count++ } }, actions: { incrementAsync ({ commit }) { setTimeout(() => { commit('increment') }, 1000) } }, getters: { getCount: state => { return state.count } } }) export default store ``` 3.在Vue组件中使用store ```javascript <template> <div> <p>Count: {{ count }}</p> <button @click="increment">Increment</button> <button @click="incrementAsync">Increment Async</button> </div> </template> <script> import { mapGetters, mapActions } from 'vuex' export default { computed: { ...mapGetters([ 'getCount' ]) }, methods: { ...mapActions([ 'increment', 'incrementAsync' ]) } } </script> ``` 在上面的示例中,我们创建了一个名为count的状态,并定义了一个名为increment的mutation和一个名为incrementAsync的action。我们还定义了一个名为getCount的getter,用于从store中获取count状态。在Vue组件中,我们使用mapGetters和mapActions帮助程序将getter和action映射到组件中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值