如何在面包屑中显示层次结构

How to display hierarchy in breadcrumb

提问人:David Jackson 提问时间:4/1/2022 最后编辑:David Jackson 更新时间:7/1/2022 访问量:605

问:

我是使用 Angular 的新手,想包含一个动态的全局面包屑。我将组件层次结构称为 component1->component2->component3->component4。 第二个组件从第一个组件获取 id,第三个组件从第二个组件获取 id,依此类推。

breadcrumb.component.html

<ul>
    <li *ngFor="let breadcrumb of (breadcrumbs$ | async)">
      <a [href]="breadcrumb.url">{{ breadcrumb.label }}</a>
    </li>
</ul>

面包屑.component.ts

import { Component } from '@angular/core';
import { Observable } from 'rxjs';

import { Breadcrumb } from 'src/models/Breadcrumb';
import { BreadcrumbService } from 'src/services/breadcrumb.service';

@Component({
  selector: 'app-breadcrumb',
  templateUrl: './breadcrumb.component.html',
  styleUrls: ['./breadcrumb.component.css']
})
export class BreadcrumbComponent {

  breadcrumbs$: Observable<Breadcrumb[]>;

  constructor(private readonly breadcrumbService: BreadcrumbService) {
    this.breadcrumbs$ = breadcrumbService.breadcrumbs$;
  }

}

面包屑模型

export interface Breadcrumb {
    label: string;
    url: string;
}

面包屑服务

import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Data, NavigationEnd, Router } from '@angular/router';
import { BehaviorSubject } from 'rxjs';
import { filter } from 'rxjs/operators';

import { Breadcrumb } from 'src/models/Breadcrumb';

@Injectable({
  providedIn: 'root'
})
export class BreadcrumbService {

  // Subject emitting the breadcrumb hierarchy
  private readonly _breadcrumbs$ = new BehaviorSubject<Breadcrumb[]>([]);

  // Observable exposing the breadcrumb hierarchy
  readonly breadcrumbs$ = this._breadcrumbs$.asObservable();

  constructor(private router: Router) {
    this.router.events.pipe(
      // Filter the NavigationEnd events as the breadcrumb is updated only when the route reaches its end
      filter((event) => event instanceof NavigationEnd)
    ).subscribe(event => {
      // Construct the breadcrumb hierarchy
      const root = this.router.routerState.snapshot.root;
      const breadcrumbs: Breadcrumb[] = [];
      this.addBreadcrumb(root, [], breadcrumbs);

      // Emit the new hierarchy
      this._breadcrumbs$.next(breadcrumbs);
    });
  }

  private addBreadcrumb(route: ActivatedRouteSnapshot, parentUrl: string[], breadcrumbs: Breadcrumb[]) {
    if (route) {
      // Construct the route URL
      const routeUrl = parentUrl.concat(route.url.map(url => url.path));

      // Add an element for the current route part
      if (route.data.breadcrumb) {
        const breadcrumb = {
          label: this.getLabel(route.data),
          url: '/' + routeUrl.join('/')
        };
        breadcrumbs.push(breadcrumb);
      }

      // Add another element for the next route part
      //this.addBreadcrumb(route.firstChild, routeUrl, breadcrumbs);
    }
  }

  private getLabel(data: Data) {
    // The breadcrumb can be defined as a static string or as a function to construct the breadcrumb element out of the route data
    return typeof data.breadcrumb === 'function' ? data.breadcrumb(data) : data.breadcrumb;
  }

}

我不确定提及路线的正确方式是什么。我尝试了多种 StackOverflow 解决方案,但它不起作用。ids存在于各个组件中,但我需要在全局级别上访问它们才能在面包屑中访问它们。

angular breadcrumbs angular-breadcrumb

评论


答:

0赞 Dm Mh 7/1/2022 #1

您的路由结构完全由您决定,但为了让您的生活更轻松,您可以将 ID 作为路由器 URL 的一部分。例如 www.host.com/category/:cId/subcategory/:scId。 通过这种方法,您可以使用 angular 路由器访问 id。

constructor(private route: ActivatedRouteSnapshot) {}
...

this.route.paramMap.get('cId');
this.route.paramMap.get('scId');

OR

this.route.params.cId;
this.route.params.scId;

如果您无法从父路由中读取参数,请考虑将 paramsInheritanceStrategy 设置为 'always' (https://angular.io/api/router/ExtraOptions)。