You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 14可展开SideNav问题:复刻NetBox布局及悬停交互异常

Angular 14 侧边栏(SideNav)复刻NetBox布局及间距问题修复

需求明确

  • 侧边栏收缩仅显示图标时,鼠标悬停切换为悬浮展开模式,移出恢复收缩状态
  • 固定(Pin)菜单时,保持侧边栏常驻显示并展示完整菜单项文本
  • 修复当前存在的布局间距异常问题

核心实现方案

1. 组件状态变量定义

在组件类中声明控制侧边栏行为的关键变量:

import { Component, ViewChild } from '@angular/core';
import { MatSidenav } from '@angular/material/sidenav';

@Component({
  selector: 'app-sidenav',
  templateUrl: './sidenav.component.html',
  styleUrls: ['./sidenav.component.scss']
})
export class SidenavComponent {
  // 侧边栏是否固定
  isPinned = false;
  // 侧边栏是否处于收缩状态
  isCollapsed = true;
  // 侧边栏显示模式:side/over
  sidenavMode: 'side' | 'over' = 'side';

  @ViewChild('sidenav') sidenav!: MatSidenav;
}

2. 模板结构调整

修改模板,添加鼠标事件监听和条件样式控制:

<mat-sidenav-container class="sidenav-container">
  <mat-sidenav
    #sidenav
    [mode]="sidenavMode"
    [opened]="true"
    [fixedInViewport]="isPinned"
    [class.is-collapsed]="isCollapsed && !isPinned"
    [class.is-pinned]="isPinned"
    (mouseenter)="handleSidenavHover(true)"
    (mouseleave)="handleSidenavHover(false)"
    class="sidenav"
  >
    <mat-nav-list>
      <a mat-list-item *ngFor="let item of menuItems">
        <mat-icon matListItemIcon>{{item.icon}}</mat-icon>
        <span matListItemLine>{{item.label}}</span>
      </a>
    </mat-nav-list>
    <button mat-icon-button class="pin-btn" (click)="togglePin()">
      <mat-icon>{{isPinned ? 'push_pin' : 'push_pin_outline'}}</mat-icon>
    </button>
  </mat-sidenav>
  <mat-sidenav-content class="sidenav-content">
    <!-- 主内容区域 -->
  </mat-sidenav-content>
</mat-sidenav-container>

3. 事件处理逻辑

实现悬停切换和固定切换的核心逻辑:

handleSidenavHover(isEntering: boolean): void {
  if (!this.isPinned) {
    this.sidenavMode = isEntering ? 'over' : 'side';
    this.isCollapsed = !isEntering;
    this.sidenav.updateSize(isEntering ? '250px' : '64px');
  }
}

togglePin(): void {
  this.isPinned = !this.isPinned;
  this.sidenavMode = 'side';
  this.isCollapsed = !this.isPinned;
  this.sidenav.updateSize(this.isPinned ? '250px' : '64px');
}

4. 间距异常修复

添加SCSS样式,消除布局偏移和过渡抖动:

.sidenav-container {
  height: 100vh;
}

.sidenav {
  transition: width 0.3s ease;
  overflow: hidden;
  width: 64px;

  &.is-pinned {
    width: 250px !important;
  }

  .pin-btn {
    position: absolute;
    bottom: 16px;
    width: 100%;
    justify-content: center;
  }
}

.sidenav.is-collapsed mat-list-item span {
  display: none;
}

.sidenav-content {
  padding-left: 64px;
  transition: padding-left 0.3s ease;

  .is-pinned ~ & {
    padding-left: 250px;
  }
}

关键说明

  • 用fixedInViewport控制侧边栏是否固定在视口,未固定时悬浮展开不会挤压主内容
  • 通过updateSize强制更新宽度,解决过渡动画中的间距跳变问题
  • 利用CSS类控制文本显示/隐藏,避免布局抖动

内容的提问来源于stack exchange,提问作者EviSvil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 22:45:33