Vuex的状态管理:module(模块)

module的基本使用

什么是Module?

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

        为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)

        每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块;

 module的局部状态

对于模块内部的 mutation 和 getter,接收的第一个参数是模块的局部状态对象

 module的命名空间

默认情况下,模块内部的action和mutation仍然是注册在全局的命名空间中的:

        这样使得多个模块能够对同一个 action 或 mutation 作出响应;

        Getter 同样也默认注册在全局命名空间;

如果我们希望模块具有更高的封装度和复用性,可以添加 namespaced: true 的方式使其成为带命名空间的模块:

        当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名;

module修改或派发根组件

如果我们希望在action中修改root中的state,那么有如下的方式:

//moudle下的home.js
const homeModule = {
  namespaced: true,  //命名空间
  state() {
    return {
      homeCounter: 100
    }
  },
  getters: {
    //这里会有四个参数
    doubleHomeCounter(state, getters, rootState, rootGetters) {
      return state.homeCounter * 2
    },
    otherGetter(state) {
      return 100
    }
  },
  mutations: {
    increment(state) {
      state.homeCounter++
    }
  },
  actions: {
    //这里一共有六个参数
    incrementAction({commit, dispatch, state, rootState, getters, rootGetters}) {
      commit("increment")
      //派发根组件,z修改也应用到根组件上
      commit("increment", null, {root: true})

      // dispatch
      // dispatch("incrementAction", null, {root: true})
    }
  }
}

export default homeModule
//命名空间在组件中的使用
<template>
  <div>
    <h2>root:{{ $store.state.rootCounter }}</h2>
    <h2>home:{{ $store.state.home.homeCounter }}</h2>
    <h2>user:{{ $store.state.user.userCounter }}</h2>

    <hr>
    <h2>{{ $store.getters["home/doubleHomeCounter"] }}</h2>

    <button @click="homeIncrement">home+1</button>
    <button @click="homeIncrementAction">home+1</button>
  </div>
</template>

<script>
  export default {
    methods: {
      homeIncrement() {
        this.$store.commit("home/increment")
      },
      homeIncrementAction() {
        this.$store.dispatch("home/incrementAction")
      }
    }
  }
</script>

module的辅助函数

如果辅助函数有三种使用方法:

        方式一:通过完整的模块空间名称来查找;

        方式二:第一个参数传入模块空间名称,后面写上要使用的属性;(也用)

        方式三:通过 createNamespacedHelpers 生成一个模块的辅助函数;(用的比比较多)

<template>
  <div>
    <hr>
    <h2>{{ homeCounter }}</h2>
    <h2>{{ doubleHomeCounter }}</h2>
    <!-- <h2>{{ doubleRootCounter }}</h2> -->
    <button @click="increment">home+1</button>
    <button @click="incrementAction">home+1</button>
    <hr>
  </div>
</template>

<script>
  import { createNamespacedHelpers, mapState, mapGetters, mapMutations, mapActions } from "vuex";
  //3.写法三需要引入
  import { useState, useGetters } from '../hooks/index'

  // const { mapState, mapGetters, mapMutations, mapActions } = createNamespacedHelpers("home")

  export default {
    computed: {
      // 1.写法一:
      // ...mapState({
      //   homeCounter: state => state.home.homeCounter
      // }),
      // ...mapGetters({
      //   doubleHomeCounter: "home/doubleHomeCounter"
      // })

      // 2.写法二:
      // ...mapState("home", ["homeCounter"]),
      // ...mapGetters("home", ["doubleHomeCounter"])

      // 3.写法三:
      ...mapState(["homeCounter"]),
      ...mapGetters(["doubleHomeCounter"])
    },
    methods: {
      // 1.写法一:
      // ...mapMutations({
      //   increment: "home/increment"
      // }),
      // ...mapActions({
      //   incrementAction: "home/incrementAction"
      // }),

      // 2.写法二
      // ...mapMutations("home", ["increment"]),
      // ...mapActions("home", ["incrementAction"]),
      
      // 3.写法三:
      ...mapMutations(["increment"]),
      ...mapActions(["incrementAction"]),
    },

    setup() {
      // {homeCounter: function}
      // const state = useState(["rootCounter"])
      // const rootGetters = useGetters(["doubleRootCounter"])
      // const getters = useGetters("home", ["doubleHomeCounter"])

      const mutations = mapMutations(["increment"])
      const actions = mapActions(["incrementAction"])

      return {
        // ...state,
        // ...getters,
        // ...rootGetters
        // ...mutations,
        // ...actions
      }
    }
  }
</script>

<style scoped>

</style>

对useState和useGetters修改

import { mapGetters, createNamespacedHelpers } from 'vuex'
import { useMapper } from './useMapper'

export function useGetters(moduleName, mapper) {
  let mapperFn = mapGetters
  if (typeof moduleName === 'string' && moduleName.length > 0) {
    mapperFn = createNamespacedHelpers(moduleName).mapGetters
  } else {
    mapper = moduleName
  }

  return useMapper(mapper, mapperFn)
}
import { mapState, createNamespacedHelpers } from 'vuex'
import { useMapper } from './useMapper'

export function useState(moduleName, mapper) {
  let mapperFn = mapState
  if (typeof moduleName === 'string' && moduleName.length > 0) {
    mapperFn = createNamespacedHelpers(moduleName).mapState
  } else {
    mapper = moduleName
  }

  return useMapper(mapper, mapperFn)
}
//useMapper.js
import { computed } from 'vue'
import { useStore } from 'vuex'

export function useMapper(mapper, mapFn) {
  // 拿到store独享
  const store = useStore()

  // 获取到对应的对象的functions: {name: function, age: function}
  const storeStateFns = mapFn(mapper)

  // 对数据进行转换
  const storeState = {}
  Object.keys(storeStateFns).forEach(fnKey => {
    const fn = storeStateFns[fnKey].bind({$store: store})
    storeState[fnKey] = computed(fn)
  })

  return storeState
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值