0

您如何保持导航组件与非平凡应用程序同步?例如,在Angular 2 的简单 Tour of Heroes 应用程序中,app.component.ts具有静态(即不变)声明式导航:

<h1>{{title}}</h1>
<nav>
  <a routerLink="/dashboard" routerLinkActive="active">Dashboard</a>
  <a routerLink="/heroes" routerLinkActive="active">Heroes</a>
</nav>
<router-outlet></router-outlet>

但在更复杂的应用程序中,导航组件通常是动态的。在我的例子中,它nav有一个sidenav、一个后退按钮、特定于组件的操作和用户信息;并且,sidenav操作会根据用户的角色而变化。这是一个相当典型的场景——想想 Google Gmail、收件箱、日历、文档等。

现在,我nav在一个单独的my-header组件中实现了*ngIf对当前组件和用户角色的大量测试——这是一场丑陋的噩梦:

<md-toolbar color="primary" class="fixed-toolbar">
  <div *ngIf="isAuthenticated()">

    <md-menu #mainmenu="mdMenu">
      <a md-menu-item routerLink="/marketplaces" routerLinkActive="active">Marketplaces</a>
      <a md-menu-item routerLink="/people" routerLinkActive="active">People</a>
      <span *ngIf="isAdministrator()">
        <md-divider></md-divider>
        <a md-menu-item routerLink="/accounts" routerLinkActive="active">Accounts</a>
      </span>
    </md-menu>
    <button *ngIf="_navigation?.toolbar == 'default'" md-icon-button [md-menu-trigger-for]="mainmenu">
      <md-icon>menu</md-icon>
    </button>

    <button *ngIf="_navigation?.toolbar == 'market'" md-icon-button
            (click)="closeAndReturn($event, 'marketplaces')"
            aria-label="Back to Marketplaces">
      <md-icon>close</md-icon>
    </button>

    <button *ngIf="_navigation?.toolbar == 'person'" md-icon-button
            (click)="closeAndReturn($event, 'users')"
            aria-label="Back to People">
      <md-icon>close</md-icon>
    </button>
  </div>

  <!-- ^^^ nightmare continues vvv -->

my-header组件简单地包含在app.component.html

<my-header></my-header>
<router-outlet></router-outlet>
<my-footer></my-footer>

但是my-header组件和my-footer组件都不在路由器树中,因此my-header注入ActivatedRoute的始终是根节点,这意味着我什至无法转换绝对后退导航:

(click)="closeAndReturn($event, 'marketplaces')"

到相对导航:

(click)="closeAndReturn($event, '../')"

这意味着在这个组件中复制路由器树以保持同步——这显然不是正确的做法......

关于如何解决保持导航组件与复杂应用程序同步这一可能非常常见的挑战的任何想法?

4

1 回答 1

0

要解决相对导航方面的问题,请侦听路由器中的事件并捕获 URL:

  constructor(private _router: Router) {
    this._router.events
            .filter( e => e instanceof NavigationEnd )
            .subscribe( e => this._currentUrl = e.url );
  }

然后,修剪最后一个 URL 段以提高一级:

  closeAndReturn(event?) {
    const url = this._currentUrl;
    const path = url.slice(0, url.lastIndexOf('/'));

    this._router.navigate([path]);
  }

HTML 更简洁,重复更少:

<button md-icon-button (click)="closeAndReturn($event)" aria-label="Back">
  <md-icon>close</md-icon>
</button>

但是 HTML 中仍然有很多重复的路由器信息。

于 2016-09-28T22:16:52.210 回答