Angular 2 根据当前路由器状态更改 sidenav 内容

Angular 2 change sidenav content depending on the current router state

我正在 Angular 开发单页应用程序 2. 我正在使用 angular material mat-sidenav 和 mat-toolbar。工具栏有 sidenav 切换按钮,用于打开 'Clients' 部分和 'Reports' 部分的按钮。这种结构在整个项目中很常见。

所以应用看起来像这样:

我必须根据路由器的当前状态更改 sidenav(和主字段)中的内容。因此,如果打开 'Clients' 部分,sidenav 应该会显示一些与客户端相关的小节。同样,对于 'Reports' 部分,只有与报告相关的小节应该可用。我该怎么做?

我通过检查 URL 路径是否包含某些指定部分来做到这一点。例如,如果你想为客户提供可见的子菜单,它可以是 '/clients' 等。那么你只需使用 *ngIf 指令:

<ul *ngIf="location.includes('/clients')">

要检查当前 URL,您必须侦听路由器更改。因此,在您拥有 sidenav 内容的组件中,您需要订阅 router.events 属性.

import { Router, NavigationEnd } from '@angular/router';
import 'rxjs/add/operator/filter';
...
export class SidenavComponent {
  location = '';
  constructor(router: Router) {
    router.events
      .filter(event => event instanceof NavigationEnd)
      .subscribe((event: NavigationEnd) => {
        this.location = event.url
      })
...

除了 NavigationEnd 路由器会发出多个其他事件,因此我们在上面的示例中过滤它们并在订阅后更新 location 属性

我已经想出如何使用布局方法来做到这一点。您可以查看使用此方法实现管理系统的示例 here

另一种选择是使用[hidden] 属性。我开始使用 *ngIf 但它重新创建了组件,在我的例子中,它重新触发了一些导致主要内容重绘的过滤。 [hidden] 允许我在不破坏组件的情况下有选择地显示内容。用法如下:

<mat-sidenav-container class="sidenav-container">
    <mat-sidenav>
        <div >
            <div [hidden]="activeContent !== 'sidenav1'">
                <p>SIDENAV 1</p>
            </div>
            <div [hidden]="activeContent !== 'sidenav2'">
                <p>SIDENAV 2</p>
            </div>
        </div>
    </mat-sidenav>

    <mat-sidenav-content>
        <p>MAIN CONTENT<p>
    </mat-sidenav-content>
</mat-sidenav-container>

备注:

  • activeContent 是组件 class 上的一个 public 字段,其中包含 sidenav 名称(或者更具体地说,string literal union type 用于 design-time 类型检查)
  • 如果您正在为 sidenav 使用 side 模式并且您的 sidenav 内容宽度不一致,您可能会发现主要内容不会调整大小以填充可用 space。我为此想出的最佳解决方案是当 sidenav 内容更改时在组件 class 中触发 this._sidenav.close().then(_ => this._sidenav.open());