【问题标题】:How to make a responsive nav-bar using Angular material 2?如何使用 Angular 材料 2 制作响应式导航栏?
【发布时间】:2026-01-26 16:35:01
【问题描述】:

我正在尝试使用Angular material 2 创建一个导航栏,该导航栏在移动设备和平板电脑等小屏幕中折叠。

我只能找到 md-button 而不是 md-menu-bar,就像在 Angular 材料中一样。

【问题讨论】:

    标签: angular angular-material2


    【解决方案1】:

    这是我用来在angular-cli 应用程序中使用 Angular2+ Material 2 和 flex-layout 构建响应式 nav-bar 的内容。

    (请访问Install Angular Material and Angular CDK

    1) 安装弹性布局

    npm install @angular/flex-layout -save
    

    2) 在您的 app.module.ts

    中包含 flex-layout
    import {FlexLayoutModule} from "@angular/flex-layout";
    

    3) 导入

    imports: [
     BrowserModule,
     FormsModule,
     HttpModule,
     RoutingModule,
     FlexLayoutModule,
    MyOwnCustomMaterialModule // Please visit the link above "Install Angular Material and Angular CDK", and check (Step 3: Import the component modules).
    ],
    

    app.component.html

    <mat-toolbar color="primary">
    
        <button mat-button routerLink="/">
        <mat-icon>home</mat-icon> 
            {{title}}</button>
    
        <!-- This fills the remaining space of the current row -->
        <span class="fill-remaining-space"></span>
        <div fxLayout="row" fxShow="false" fxShow.gt-sm>
            <button mat-button routerLink="/products">Products</button>
            <button mat-button routerLink="/dashboard">Dashboard</button>
        </div>
        <button mat-button [mat-menu-trigger-for]="menu" fxHide="false" fxHide.gt-sm>
         <mat-icon>menu</mat-icon>
        </button>
    
    </mat-toolbar>
    <mat-menu x-position="before" #menu="matMenu">
        <button mat-menu-item routerLink="/products">Products</button>
        <button mat-menu-item routerLink="/dashboard">Dashboard</button>
        <!--<button mat-menu-item>Help</button>-->
    </mat-menu>

    app.component.css

    .fill-remaining-space {
       /*This fills the remaining space, by using flexbox.  
      Every toolbar row uses a flexbox row layout. */
      flex: 1 1 auto;
    }

    注意:要测试,请调整页面大小。

    看看flex-layout docs

    【讨论】:

    • 效果很好。感谢您对 flex-layout 的关注。没听说过。
    • 很酷的解决方案。请记住 FlexLayoutModule.forRoot() 已被弃用。我们现在只使用 FlexLayoutModule
    • 想提个小建议:在折叠时显示的菜单中使用md-menu-item 可能比较合适
    • angular-material 已更改大多数组件的名称。这个 sn-p 在 angular-material 5.0.2 中不起作用
    • @Ruben 好问题.. 我也是这么想的,Angular 推出的第一件事就是一个简单的响应式菜单,对吧??
    【解决方案2】:

    这是我最喜欢在 Angular 中创建响应式导航栏的方式。如果您使用 Angular 6,请确保您使用的是 6.1+
    Stackblitz 上的工作示例:https://stackblitz.com/edit/angular-v6xwte

    小屏幕上的示例:

    大屏幕上的示例:

    以下是具体的操作步骤:

    1) 安装必要的软件包。输入你的终端:

    npm install --save @angular/material @angular/cdk @angular/animations
    
    npm install @angular/flex-layout --save
    

    2) 在你的 app.module.ts 中导入必要的模块

    import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
    import { FlexLayoutModule } from '@angular/flex-layout';
    import {
      MatIconModule, MatButtonModule, MatSidenavModule, MatToolbarModule
    } from '@angular/material';
    

    记得将这些模块添加到下面的导入数组中。

    3) 将 Material Icons 链接添加到您的 index.html
    该链接必须位于任何 Angular 内容之前。

    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
    

    4) 在你的 styles.css 中添加一个 Angular 主题并将边距设置为 0%

    @import "~@angular/material/prebuilt-themes/indigo-pink.css";
    body{
        margin: 0%;
    }
    

    5) 在你的 app.component.html 中添加工具栏 HTML 代码

    <div style="height: 100vh;"> 
    <mat-toolbar color="primary">
        <div fxShow="true" fxHide.gt-sm="true">
          <button mat-icon-button (click)="sidenav.toggle()">
            <mat-icon>menu</mat-icon>
          </button>
        </div>
        <a mat-button class="companyName" routerLink="/">
          <span>Site name</span>
        </a>
        <span class="example-spacer"></span>
        <div fxShow="true" fxHide.lt-md="true">
          <a mat-button routerLink="/about-us">About us</a>
          <a mat-button routerLink="/prices">Prices</a>
          <a mat-button routerLink="/start-page">Start page</a>
          <a mat-button routerLink="/offer">Offer</a>
          <a mat-button routerLink="/contact">Contact</a>
        </div>
      </mat-toolbar>
      <mat-sidenav-container fxFlexFill class="example-container">
        <mat-sidenav color="primary" #sidenav fxLayout="column" mode="over" opened="false" fxHide.gt-sm="true">
          <div fxLayout="column">
            <a mat-button routerLink="/about-us">About us</a>
            <a mat-button routerLink="/prices">Prices</a>
            <a mat-button routerLink="/start-page">Start page</a>
            <a mat-button routerLink="/offer">Offer</a>
            <a mat-button routerLink="/contact">Contact</a>
          </div>
        </mat-sidenav>
        <mat-sidenav-content fxFlexFill>
          Awesome content
        </mat-sidenav-content>
      </mat-sidenav-container>
    </div>
    

    6) 在 app.component.css 中设置工具栏样式

    .companyName{
        font-size: 150%;
    }
    div {
        overflow: inherit;
    }
    a{
        text-decoration: none;
        font-size: 110%;
        white-space: normal;
    }
    button{
        font-size: 110%;
        min-width: min-content;
    }
    .example-icon {
        padding: 0 14px;
      }
    
      .example-spacer {
        flex: 1 1 auto;
      }
      .mat-sidenav-content{
          font-size: 200%;
          text-align: center;
      }
    

    【讨论】:

    【解决方案3】:

    使用 Material 创建响应式导航栏的最简单方法是使用 Angular CLI schematics

    (如果您在运行 ng add @angular/material 时收到“无法解析集合“@angular/material”,请参阅this

    然后使用生成的组件&lt;app-my-nav&gt;&lt;/app-my-nav&gt; 将上述标签添加到您的主要组件中

    台式电脑上的响应式视图:

    低分辨率的响应式折叠菜单:

    最初是在 Angular's blog 上看到的。

    【讨论】:

    • 在哪里记录了 angular cli 的这种使用?
    【解决方案4】:

    查看 github 上的 angular2-material 项目。以下是他们迄今为止发布的材料设计组件列表:

    https://www.npmjs.com/~angular2-material

    另外,我认为md-sidenavmd-toolbar 是您正在寻找的。

    md-sidenav - https://www.npmjs.com/package/@angular2-material/sidenav

    md-toolbar - https://www.npmjs.com/package/@angular2-material/toolbar

    注意:该项目仍处于 alpha 版本,这意味着他们的 API 可能会发生重大变化。不建议在生产中使用。

    【讨论】:

      【解决方案5】:

      我粗略地尝试使用带有抽屉实现的工具栏修改答案,并使用 angular-material 5.0.2 的新组件名称

      待办事项:需要修复所有标题链接的 CSS。菜单图标应该是透明的。

      https://responsivematerial2.stackblitz.io/

      .mat-sidenav-container {
        background: rgba(0, 0, 0, 0.08);
      }
      
      .blank-grow {
        flex: 1 1 auto;
      }
      <mat-sidenav-container fullscreen>
        <mat-sidenav #sidenav>
          <mat-nav-list>
            <a mat-list-item>
              <mat-icon mat-list-icon>home</mat-icon>
              <span mat-line>home</span>
            </a>
      
            <a mat-list-item>
              <mat-icon mat-list-icon>backup</mat-icon>
              <span mat-line>Backup</span>
            </a>
          </mat-nav-list>
        </mat-sidenav>
        <mat-toolbar color="primary">
          <button mat-icon-button (click)="sidenav.open()" fxHide="false" fxHide.gt-sm>
            <mat-icon>menu</mat-icon>
          </button>
          <span> Big Header</span>
          <span class="blank-grow"></span>
          <div fxLayout="row" fxShow="false" fxShow.gt-sm>
            <a>
              <mat-icon mat-list-icon>home</mat-icon>
              <span mat-line>home</span>
            </a>
      
            <a>
              <mat-icon mat-list-icon>backup</mat-icon>
              <span mat-line>Backup</span>
            </a>
          </div>
        </mat-toolbar>
      </mat-sidenav-container>

      【讨论】:

      【解决方案6】:

      我已经编辑了 user2662006 的答案,并在下面进行了一些修复和代码优化。请注意,我的 * 积分目前太低,甚至无法授予我提交评论的权限,更不用说编辑了。

      1) Install Angular Material and Angular CDK

      2) 安装弹性布局

      npm install @angular/flex-layout -save
      

      3) 在您的 app.module.ts

      中包含 flex-layout
      import {FlexLayoutModule} from "@angular/flex-layout";
      

      4) 导入相关材质和弹性模块

      imports: [
       ...,
       FlexLayoutModule,
       MatToolbarModule,
       MatIconModule,
       MatMenuModule,
       MatButtonModule,
      ],
      

      app.component.html

      <mat-toolbar color="primary">
          <button mat-button routerLink="/">
              <mat-icon>home</mat-icon> 
              {{title}}
          </button>
      
          <span class="fill-remaining-space"></span>
      
          <div fxLayout="row" fxHide fxShow.gt-sm>
              <button mat-button routerLink="/products">Products</button>
              <button mat-button routerLink="/dashboard">Dashboard</button>
          </div>
          <button mat-button [mat-menu-trigger-for]="menu" fxShow fxHide.gt-sm>
           <mat-icon>menu</mat-icon>
          </button>
      
      </mat-toolbar>
      <mat-menu x-position="before" #menu>
          <button mat-menu-item routerLink="/products">Products</button>
          <button mat-menu-item routerLink="/dashboard">Dashboard</button>
      </mat-menu>
      

      app.component.css

      .fill-remaining-space {
         /*This fills the remaining space, by using flexbox.  
        Every toolbar row uses a flexbox row layout. */
        flex: 1 1 auto;
      }
      

      注意事项:

      【讨论】:

      • 如何添加嵌套菜单?
      【解决方案7】:

      我的演示文稿Create Enterprise UIs That Your Users Will Love 涵盖了 Angular Material 的其中一些模式。 StackBlitz 示例的链接位于演讲者备注中。

      带有溢出菜单的响应式按钮栏: 这可以放置在 TopNav 中或下方。 https://stackblitz.com/edit/material-responsive-button-bar?file=app%2Fbutton-bar%2Fbutton-bar.component.ts

      动态嵌套 TopNav 菜单: 请注意,此菜单并非完全可访问。需要做更多的工作才能完全支持良好的 a11y 体验。 https://stackblitz.com/edit/dynamic-nested-topnav-menu?file=app/app.component.ts

      动态嵌套 SideNav 菜单: 如果您使用转换模式将您的 TopNav 切换到移动设备上的 SideNav,这将展示如何构建动态 SideNav 菜单。 https://stackblitz.com/edit/dynamic-nested-sidenav-menu?file=app%2Fapp.component.html

      【讨论】:

        【解决方案8】:

        您可以使用mat-toolbarmat-sidenavflex-layoutfxFlexFill,...)来构建响应式菜单。

        See Stackblitz example.

        More info...

        【讨论】: