VueX3 自动化导入模块

2021-12-24

一个使用 Vue2 构建的应用越来越复杂,随着而来的是应用状态的复杂;这时就需要根据功能或组件将 VueXstore 进行模块化。 应用的初始化除了大体框架搭建、功能目录的划分、工具的封装外等,更加抽象化的操作都是需要随着开发慢慢推进。大部分起始创建的 store 中,无需进行模块的划分,只需要提供创建 store 实例的 state\getters\actions\mutations 参数。 当将应用状态进行模块的划分,最简单地莫不过是如下

// 目录结构
// store
//     -- index.js
//    |-- modules
//         -- cart.js
//         -- products.js
//    	  |-- info
//            -- actions.js
//            -- getters.js
//            -- index.js
//            -- mutations.js
//            -- state.js

// index.js
import Vue from 'vue'
import Vuex from 'vuex'
import cart from './modules/cart'
import products from './modules/products'

Vue.use(Vuex)

export default new Vuex.Store({
  modules: {
    cart,
    products,
  },
})
// cart.js/products.js
const state = {}
const getters = {}
const actions = {}
const mutatios = {}

export default {
  namespaced: true,
  state,
  getters,
  actions,
  mutatios,
}

手动导入指定模块只适用于模块数量不多的情况;可以使用 webpack 提供的 require.context 方法,遍历指定文件目录并可加载指定文件

// 在 store\index.js 同级下创建 modules.js 文件
// 指定导入当前 modules 文件目录中的 js 文件
const _files = require.context('./modules', true, /\.js$/)

const modules = _files.keys().reduce((modules, path) => {
  if (path.indexOf('.js')) {
    const name = path.replace(/^\.\/|.js$/g, '')
    modules[name] = _files(path).default
    return modules
  }
  return modules
}, {})

export default modules
// 在 store\index.js 中引入 modules.js 文件
import Vue from 'vue'
import Vuex from 'vuex'
import modules from './modules'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {},
  mutations: {},
  actions: {},
  modules,
})
<template>
  <div>
    <span>{{ state1 }}</span>
  </div>
</template>
<script>
import { mapState } from 'vuex'
export default {
  computed: {
    ...mapState('cart', ['state1']),
  },
}
</script>

随着模块数量增加和操作的复杂,单个 js 文件不能再满足单个模块的复杂度;此时可以将模块拆分为目录结构,目录中 js 文件划分为 index、state、getters、types、actions、mutations

// 指定导入当前 modules 文件目录中的 js 文件
const _files = require.context('./modules', true, /\.js$/)
// 过滤指定名称的文件
const _ignoreFiles = ['states', 'getters', 'actions', 'types', 'mutations']

const modules = _files.keys().reduce((modules, path) => {
  if (path.indexOf('.js') && !_ignoreFiles.filter((file) => path.includes(file)).length) {
    const name = path.replace(/^\.\/|.js$/g, '').replace(/\/index$/g, '')
    modules[name] = _files(path).default
    return modules
  }
  return modules
}, {})

export default modules

replace(/\/index$/g, '') 是把一个模块由多个文件组成的情况,在使用时指定路径简化为模块文件夹路径即可。

export default {
    data() {},
    computed: {
        // ...mapState('info/index', ['state1'])
        ...mapState('info', ['state1'])
    }
}
cd ..