目录
一、背景
1、俩个不同项目,但是系统菜单及系统菜单下的模块都是一样的。
2、其他图形化模块也基本一致。
3、首页地图相关模块也是一致的。
为了方便后期维护,使公共组件和相同模块能够复用,因此想用差异化管理的形式来进行架构搭建,及代码管理。
二、解决方案
1、动态注入必要的配置参数
具体实现可参考angular6 启动前注入一些配置参数
2、路由重置
- 1)将公共的路由配置完,将差异的部分动态配置
公共的路由配置
const routes: Routes = [ { path: '', component: LayoutDefaultComponent, children: [ { path: 'soc', loadChildren: './soc/soc.module#SocModule', canActivate: [LoginGuard], }, { path: 'scan', loadChildren: './scan/scan.module#ScanModule', canActivate: [LoginGuard], }, { path: 'upms', loadChildren: './systems/upms.module#UpmsModule', canActivate: [LoginGuard], }, ], canActivateChild: [LoginGuard], }, // passport { path: 'passport', component: LayoutPassportComponent, children: [ { path: 'login', component: UserLoginComponent, data: { title: '登录', titleI18n: 'pro-login' }, }, ], }, // 单页不包裹Layout { path: 'callback/:type', component: CallbackComponent }, { path: 'lock', component: UserLockComponent, data: { title: '锁屏', titleI18n: 'lock' }, }, { path: '403', component: Exception403Component }, { path: '404', component: Exception404Component }, { path: '500', component: Exception500Component }, { path: '**', redirectTo: 'dashboard', canActivate: [LoginGuard] }, ];
差异的路由配置
差异一
import { Routes } from '@angular/router'; import { LoginGuard } from '@core/guard/guard.service'; import { DashboardV1Component } from '@scan/dashboard/v1.component'; export const SCANTreeCfg: Routes = [ { path: '', redirectTo: 'dashboard/v1', pathMatch: 'full', canActivate: [LoginGuard], }, { path: 'dashboard', redirectTo: 'dashboard/v1', pathMatch: 'full', canActivate: [LoginGuard], }, { path: 'dashboard/v1', component: DashboardV1Component, canActivate: [LoginGuard], } ];
差异二
import { Routes } from '@angular/router'; import { LoginGuard } from '@core/guard/guard.service'; import { DashboardV1Component } from '@soc/dashboard/v1.component'; export const SOCTreeCfg: Routes = [ { path: '', redirectTo: 'dashboard/v1', pathMatch: 'full', canActivate: [LoginGuard], }, { path: 'dashboard', redirectTo: 'dashboard/v1', pathMatch: 'full', canActivate: [LoginGuard], }, { path: 'dashboard/v1', component: DashboardV1Component, canActivate: [LoginGuard], } ];
- 2)新建服务,处理这些需要动态加载的路由参数(此处有个问题,由于使用了预先加载,此处需要将多余的路由删除)
/** * 该服务用于解决菜单项相关配置,处理不同产品下加载不同的树 */ import { ConfigureService} from '@core/configure/configure.service'; import { Injectable } from '@angular/core'; import { Router, NavigationEnd } from '@angular/router'; import { SCANTreeCfg } from '@scan/SCAN.teee'; import { SOCTreeCfg } from '@soc/SOC.teee'; @Injectable() export class TreeService { constructor( private config: ConfigureService, private router: Router ) { } /** * 不同的产品 获取不同的树文件 * @returns {any} */ public getTree() { const module = this.config.getProject; let treeCfg; switch (module) { case 'SOC': treeCfg = SOCTreeCfg; break; case 'SCAN': treeCfg = SCANTreeCfg; break; default: treeCfg = SOCTreeCfg; } return treeCfg; } /** * 将另一个项目的路由配置删除掉 * @param cfg * @returns {any} */ private getDefaultConfig(cfg) { const module = this.config.getProject; for (let i = 0; i < cfg.length; i++) { const path = cfg[i].path; if (path !== module.toLowerCase() && path !== 'upms') { cfg.splice(i, 1); } } return cfg; } /** * 重新设置路由 */ resetRouterConfig() { const config = this.router.config; const treeCfg = this.getTree(); const cfg = this.getDefaultConfig(config[0].children); config[0].children = [...treeCfg, ...cfg]; this.router.resetConfig(config); } /** * 根据配置获取当前的树 * @param key * @returns {any} */ private getTreeDataByKey(key) { return this[key]; } }
- 3)在项目根目录app-root下执行resetRouterConfig
constructor( private settings: SettingsService, private router: Router, private titleSrv: TitleService, private treeService: TreeService, ) { treeService.resetRouterConfig(); }
4)小功能点的差异处理
这种差异虽然可以使用dom隐藏的方式进行处理,但是模块内部有些逻辑也需要兼顾,且安全上也不友好,因此通过组件动态加载的方式进行实现。实现方式如
3、webpack分包配置