美文网首页
基于Vue-cli初始化项目的多项目管理

基于Vue-cli初始化项目的多项目管理

作者: 说叁两事 | 来源:发表于2021-02-13 17:18 被阅读0次

    在Vue-cli 3.X环境下,基于同一类型的活动,可以多个页面复用,大部分组件可以公用的背景

    Multiple处理方式

    • 每一个活动创建一个分支,在不同的分支上各自维护
    • 如果需要维护复用代码时,任选某一分支进行修改,通过git cherry-pick <commit id>进行平行迁移。

    Monorepo处理方式

    仅在同一分钟下进行多项目的维护,各个功能模块解构,通过项目配置项进行个性化配置。

    目录结构

    |-src  
      |- views
        |- index.js // 通用页面的统一入口
        |- Company
          |- index.vue // 通用页面Company结构、样式、逻辑
          |- index.js  // Company页面路由
        |- Rule
          |- index.vue
          |- index.js
      |- components
      |- core
        |- instance  // 和app实例挂钩的方法
        |- libs  // 和app实例无关的方法
      |- assets
        |- images
        |- fonts
      |- store
        |- index.js  // 通用状态
        |- types.js  // 事件类型
      |- config
        |- proA.js  // 项目资源配置
        |- proB.js
      |- projects  // 项目定制资源
        |- proA
        |- proB
    

    不同项目的区别完全在于config/文件的配置和projects/下的项目定义;同级其余目录是各个项目通用的内容。

    提取公共页面 & 路由

    公共页面示例:
    // src/views/Company/index.vue
    <template>
     ...
    </template>
    <script>
    ...
    </script>
    <style scoped>
    ...
    </style>
    
    公共页面路由
    // src/views/Company/index.js
    export default [
      {
        path: '/company',
        name: 'company',
        component: () => import(/* webpackChunkName: "company" */ './index.vue'),
        meta: {
          title: '公司简介'
        }
      }
    ]
    
    公共页面统一入口
    // src/views/index.js
    export { default as companyRoute } from './Company/index.js'
    export { default as ruleRoute } from './Rule/index.js'
    
    定制项目中的公共页面
    // src/config/proA.js
    import {
      companyRoute,
      ruleRoute
    } from '../views/index.js'
    ...
    export const logoUrl = '' // 还可以定制其它的内容
    
    export const routes = [
      ...companyRoute,
      ...ruleRoute
    ]
    
    项目中使用公共页面

    src/projects/proA为例:

    目录结构

    |- assets
    |- components
    |- mixins
    |- router
    |- store
    |- pages
    |- App.vue
    |- main.js
    

    项目主路由

    // src/projects/proA/router/index.js
    import Vue from 'vue'
    import Router from 'vue-router'
    import { routes } from '../../config/proA'
    import Home from '../pages/Home'
    
    Vue.use(Router)
    
    export default new Router({
      routes: [
        {
          path: '/',
          redirect: '/home'
        },
        {
          path: '/home',
          name: 'Home',
          component: Home,
          meta: {
            title: ''
          }
        },
        ...routes
      ]
    })
    

    其中:Home/index.vue是定制化的。

    状态管理

    多项目是独立运行时,状态提取不会互相干扰,若一次性运行多个项目,通用状态会被修改。

    通用状态提取
    // src/store/index.js
    import types from './types'
    
    export const initialState = {
      userInfo: {},
      ...
    }
    export function getGetters (store) {
      return {
        userId: () => store.userInfo.userID,
        ...
      }
    }
    export function getMutations (store) {
      return {
        [types.INITIALMUTATIONTYPES.USER_INFO] (val) {
          store.userInfo = val
        },
        ...
      }
    }
    

    config/proA.js文件中追加:

    ...
    export * from '../store/index.js'
    export * from '../store/types.js'
    ...
    
    项目中使用

    小型项目,使用vue.observable管理状态

    定义项目的主状态管理
    // src/projects/proA/store/index.js
    
    import vue from 'vue'
    import { initialState, getGetters, getMutations } from '../../../config/proA'
    
    export const store = vue.observable({
      ...initialState,
      customState: '', // 项目私有状态
      ...
    })
    store._getters = {
      ...getGetters(store),
      customGetter() {  // 项目私有
          return store.customState
      },
      ...
    }
    store._mutations = {
      ...getMutation(store),
      ...  // 项目私有
    }
    export const mutation = {
      ...getMutations(store),
      ...  // 项目私有
    }
    
    定义辅助方法mapGetters

    拷贝vuex部分代码到src/core/libs/helpers.js文件中

    export const mapGetters = (getters) => {
      const res = {}
      if (!isValidMap(getters)) {
        console.error('[vuex] mapGetters: mapper parameter must be either an Array or an Object')
      }
      normalizeMap(getters).forEach(({ key, val }) => {
        res[key] = function mappedGetter () {
          if (!(val in this.$store._getters)) {
            console.error(`[vuex] unknown getter: ${val}`)
            return
          }
          return this.$store._getters[val]()
        }
      })
      return res
    }
    export function normalizeMap (map) {
      if (!isValidMap(map)) {
        return []
      }
      return Array.isArray(map)
        ? map.map(key => ({ key, val: key }))
        : Object.keys(map).map(key => ({ key, val: map[key] }))
    }
    export function isValidMap (map) {
      return Array.isArray(map) || isObject(map)
    }
    export function isObject (obj) {
      return obj !== null && typeof obj === 'object'
    }
    

    /src/core/libs/index.js中追加:

    export * from './helpers'
    
    *.vue中使用
    // src/projects/proA/pages/Home/index.vue
    <script>
    ...
    import { mapGetters } from '../../../core/libs/'
    
    export default {
      data () {
        return {
          ...
        }
      },
      computed: {
        ...mapGetters([
            'userId'
        ]),
        ...
      }
    ...
    </script>
    

    组件管理

    组件统一入口

    借助webpackrequire.context方法将/components/下的组件整合

    const ret = {}
    const requireComponent = require.context(
      './',  // 指定递归的文件目录
      true,  // 是否递归文件子目录
      /[A-Z]\w+\.(vue)$/  // 落地文件
    )
    requireComponent.keys().forEach(fileName => {
      const componentConfig = requireComponent(fileName)
      const component = componentConfig.default || componentConfig
      const componentName = component.name || fileName.split('/').pop().replace(/\.\w+$/, '')
      // ret[componentName] = () => requireComponent(fileName)
      ret[componentName] = component
    })
    export default ret
    
    定义布局配置
    // config/proA.js追加
    ...
    export const layouts = {
      Home: [
        {
          componentType: 'CompA',
          request: {
            fetch () {
              const res = []
              return res
            }
          },
          response: {
            filter (res) {
              return []
            },
            effect () {
    
            }
          }
        },
        {
          componentType: 'CompB'
        },
        {
          componentType: 'CompC'
        },
        {
          componentType: 'CompD'
        }
      ]
    }
    
    项目中使用

    proA/Home/index.vue

    <template>
    ...
      <template v-for="componentConfig of layouts">
        <component
          v-bind="dataValue"
          :is="componentConfig.componentType"
          :key="componentConfig.componentType"
        >
        </component>
      </template>
    ...
    </template>
    <script>
    ...
    import {
      CompA,
      CompB
    } from '../../components/'
    import { layouts } from '../../config/proA'
    ...
    export default {
      ...
      data () {
        return {
          ...
          layouts: layouts.Home,
          ...
        }
      },
      ...
      components: {
        CompA,
        CompB
      },
      ...
    }
    </script>
    

    参考文档

    相关文章

      网友评论

          本文标题:基于Vue-cli初始化项目的多项目管理

          本文链接:https://www.haomeiwen.com/subject/lwnsxltx.html