Angular中基于角色控制仪表盘展示有哪些替代ngSwitch的实现方案?
Angular 角色仪表盘无需ngSwitch的实现方案
下面是三种生产环境常用的替代实现,扩展性和可维护性都比硬编码ngSwitch更好:
方案1:使用NgComponentOutlet动态渲染组件
这个方案是最直接的ngSwitch替代,不需要改动路由逻辑,组件映射关系集中维护,新增角色只需要修改映射表即可。
步骤1:修改component.ts代码
import { NgComponentOutlet } from '@angular/common'; // 先引入所有要用到的仪表盘组件 import { HeaderComponent } from './xxx/header.component'; import { SystemIntegratorDashboardComponent } from './xxx/system-integrator-dashboard.component'; import { OrganizationAdminDashboardComponent } from './xxx/organization-admin-dashboard.component'; import { OrganizationUserDashboardComponent } from './xxx/organization-user-dashboard.component'; export class DashboardComponent implements OnInit { userRole: string; // 集中维护角色和组件的映射关系 roleComponentMap = new Map<string, any>([ ['SuperAdmin', HeaderComponent], ['Admin', SystemIntegratorDashboardComponent], ['AdminUser', OrganizationAdminDashboardComponent], ['User', OrganizationUserDashboardComponent] ]); // 要渲染的目标组件 targetDashboardComponent?: any; constructor(private authService: AuthService) { this.userRole = this.authService.userRole(); this.targetDashboardComponent = this.roleComponentMap.get(this.userRole); } }
步骤2:修改html模板代码
<!-- 只需要一行代码即可渲染对应组件,角色再多也不会臃肿 --> <ng-container *ngComponentOutlet="targetDashboardComponent"></ng-container>
如果需要给组件传参,可以配合NgComponentOutlet的ngComponentOutletInputs属性使用,直接把参数对象传入即可。
方案2:路由子模块+角色路由重定向
这个方案适合不同角色仪表盘逻辑差异大的场景,每个角色的仪表盘可以单独做懒加载、单独维护,代码耦合度更低。
步骤1:配置路由规则
在你的路由配置文件中添加仪表盘子路由:
const routes: Routes = [ { path: 'dashboard', component: DashboardComponent, children: [ { path: 'super-admin', component: HeaderComponent, canActivate: [RoleGuard], data: { allowedRoles: ['SuperAdmin'] } }, { path: 'admin', component: SystemIntegratorDashboardComponent, canActivate: [RoleGuard], data: { allowedRoles: ['Admin'] } }, { path: 'admin-user', component: OrganizationAdminDashboardComponent, canActivate: [RoleGuard], data: { allowedRoles: ['AdminUser'] } }, { path: 'user', component: OrganizationUserDashboardComponent, canActivate: [RoleGuard], data: { allowedRoles: ['User'] } }, { path: '', redirectTo: 'user', pathMatch: 'full' } ] } ]
步骤2:在DashboardComponent中触发重定向
export class DashboardComponent implements OnInit { userRole: string; // 维护角色和路由路径的映射 rolePathMap = new Map<string, string>([ ['SuperAdmin', 'super-admin'], ['Admin', 'admin'], ['AdminUser', 'admin-user'], ['User', 'user'] ]); constructor(private authService: AuthService, private router: Router, private route: ActivatedRoute) { this.userRole = this.authService.userRole(); const targetPath = this.rolePathMap.get(this.userRole) || 'user'; this.router.navigate([targetPath], { relativeTo: this.route }); } }
步骤3:html模板只需要留路由出口
<router-outlet></router-outlet>
方案3:自定义结构型指令
如果项目中多个地方都需要根据角色显示内容,可以封装一个通用的*appRoleIf指令,复用性最高:
步骤1:封装角色判断指令
@Directive({ selector: '[appRoleIf]' }) export class RoleIfDirective { @Input() set appRoleIf(allowedRoles: string[]) { const currentRole = this.authService.userRole(); if (allowedRoles.includes(currentRole)) { this.viewContainer.createEmbeddedView(this.templateRef); } else { this.viewContainer.clear(); } } constructor( private templateRef: TemplateRef<any>, private viewContainer: ViewContainerRef, private authService: AuthService ) {} }
步骤2:模板中直接使用指令
<app-header-component title="Dashboard" *appRoleIf="['SuperAdmin']"></app-header-component> <app-system-integrator-dashboard *appRoleIf="['Admin']"></app-system-integrator-dashboard> <app-organization-admin-dashboard *appRoleIf="['AdminUser']"></app-organization-admin-dashboard> <app-organization-user-dashboard *appRoleIf="['User']"></app-organization-user-dashboard>
内容的提问来源于stack exchange,提问作者Ragu
相关产品推荐
相关产品推荐

