这个是我自己写项目时遇到的问题
项目的侧边菜单用的是 Material Sidenav + Bootstrap Accordion 混合实现, 所以存在一些小 Bug. 在正常情况下点击 System, 点击 User, 那么 User 菜单是能正常激活的 (携带 .active 这个类)
但是如果这个时候我按 F5 刷新页面, 菜单就变成这样了
页面还是 User 页, 但是 System 菜单的展开效果消失了
检查元素时看到, 内部 User 菜单是激活状态, 但是父菜单的 class 没有同步
因为当时代码是这样写的
layout.component.html
<mat-sidenav-container id="page-sidenav-container">
<mat-sidenav #sidenav mode="side" opened>
<rxc-sidenav-logo></rxc-sidenav-logo>
<rxc-sidenav-menus></rxc-sidenav-menus>
</mat-sidenav>
<mat-sidenav-content>
<main>
<mat-toolbar>
<button mat-icon-button (click)="sidenav.toggle()">
<mat-icon>menu</mat-icon>
</button>
</mat-toolbar>
<rxc-wrapper>
<div class="rxc-wrapper-content">
<router-outlet></router-outlet>
</div>
</rxc-wrapper>
</main>
</mat-sidenav-content>
</mat-sidenav-container>
sidenav-menus.component.html
<ul id="sidenav-menus" class="accordion accordion-flush">
<li *ngFor="let menu of menus" class="accordion-item">
<rxc-sidenav-link [menu]="menu"></rxc-sidenav-link>
<ul *ngIf="menu.children" id="{{ menu.link }}" class="collapse" data-bs-parent="#sidenav-menus">
<li *ngFor="let child of menu.children">
<rxc-sidenav-link [menu]="child"></rxc-sidenav-link>
</li>
</ul>
</li>
</ul>
sidenav-link.component.html
<a #element matRipple [matRippleColor]="'rgba(230, 240, 250, .175)'"
[ngClass]="{'active':menu.link === router.routerState.snapshot.url}" (click)="onMenuClick(menu)">
<mat-icon [ngClass]="{'ms-3':menu.type === MenuType.SIDENAV_INSIDE}">{{ menu.icon }}</mat-icon>
<span>{{ menu.name | translate }}</span>
</a>
sidenav-link.component.ts
import { AfterViewInit, Component, ElementRef, Input, ViewChild } from '@angular/core';
import { Router } from '@angular/router';
import { MenuType } from 'src/app/base/enumeration/menu-type';
import { SidenavLink } from 'src/app/base/model/sidenav-link.model';
@Component({
selector: 'rxc-sidenav-link',
templateUrl: './sidenav-link.component.html',
styleUrls: ['./sidenav-link.component.scss']
})
export class SidenavLinkComponent implements AfterViewInit {
@Input() menu!: SidenavLink;
@ViewChild('element') element!: ElementRef<HTMLParagraphElement>;
constructor(public router: Router) { }
public get MenuType() {
return MenuType;
}
ngAfterViewInit(): void {
if (this.menu.type === MenuType.SIDENAV_COLLAPSE) {
this.element.nativeElement.setAttribute('href', '#' + this.menu.link);
this.element.nativeElement.setAttribute('data-bs-toggle', 'collapse');
this.element.nativeElement.classList.add('accordion-button', 'collapsed');
}
}
onMenuClick(menu: SidenavLink) {
if (menu.type !== MenuType.SIDENAV_COLLAPSE) {
this.router.navigate([menu.link]);
}
}
}
a 标签中 ngClass 的判断, 如果当前路由和菜单对应的路由相等, 则 .active
激活当前菜单
但是我在外部的页面 sidenav-menus.component.html
没有加任何的判断, 所以导致父级不生效
所以才出现这样的需求场景, 可以简单理解为如下代码
<!-- 如果里面的div携带 .active 类, 则给外面的 div 增加一个 .show 类, 反之则删除 -->
<section>
<div>
<div class="active"></div>
</div>
<div>
<div></div>
</div>
</section>
有没有什么方法能解决这个问题? 或者好一点的思路?
在 Bootstrap 中有没有对应的解决方案?
其实大可不必这么麻烦,有个
RouterLinkActive
指令可以帮你做这些https://angular.io/api/router...