基于Vue-cli初始化项目的多项目管理
Posted 米花儿团儿
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于Vue-cli初始化项目的多项目管理相关的知识,希望对你有一定的参考价值。
在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>
组件管理
组件统一入口
借助webpack
的require.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不同环境打包命令配置: 大部分内容来源
- 使用 MonoRepo 管理前端项目
以上是关于基于Vue-cli初始化项目的多项目管理的主要内容,如果未能解决你的问题,请参考以下文章