Angular 6 breadcrumb 面包屑

一、前期准备

  1. 面包屑组件(最好能封装成共享组件)
  2. 一些路由信息配置
  3. Ant-Zorro 组件的环境配置(这里会套用里面的一些现成的组件库),版本: 7.0.1

二、Ant-Zorro 配置

这里请参考官方网站 https://ng.ant.design/docs/getting-started/zh ,官方网站中,找到目录 快速上手 ,在里面有 自行构建,查看 自行构建 下的内容。

如果依然不能成功,可以浏览参考博主的另一个博客:
里面讲了一些博主在配置 Ant-Zorro 的时候遇到的坑!

三、自定义面包屑组件

1. 创建一个自己的面包屑组件

ng g c breadcrumb --spec=false

2. 使用 Ant-Zorro 的面包屑组件

<nz-breadcrumb>
    <nz-breadcrumb-item>Home</nz-breadcrumb-item>
    <nz-breadcrumb-item><a>Application List</a></nz-breadcrumb-item>
    <nz-breadcrumb-item>An Application</nz-breadcrumb-item>
</nz-breadcrumb>

将 Ant-Zorro 组件库中的面包屑组件,放到自己创建的面包屑组件的html文件中。将组件库中的面包屑做一点改动,将静态的面包屑改成动态的,使用 ngFor 循环自行加载,对应的路由信息。

<nz-breadcrumb>
  <nz-breadcrumb-item>首页</nz-breadcrumb-item>
  <nz-breadcrumb-item *ngFor="let breadcrumb of breadcrumbs">
    <a [routerLink]="[breadcrumb.url, breadcrumb.params]">{{ breadcrumb.label }}</a>
  </nz-breadcrumb-item>
</nz-breadcrumb>

3. 面包屑逻辑代码

import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute, NavigationEnd, Params, PRIMARY_OUTLET } from '@angular/router';
import { filter } from 'rxjs/operators';

interface IBreadcrumb {
  label: string;
  params: Params;
  url: string;
}

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

export class BreadcrumbComponent implements OnInit {
  public breadcrumbs: IBreadcrumb[];

  constructor(
    private activatedRoute: ActivatedRoute,
    private router: Router
  ) {
    this.breadcrumbs = [];
  }

  ngOnInit() {
    // 订阅NavigationEnd事件
    this.router.events.pipe(filter(event => event instanceof NavigationEnd))
      .subscribe(event => {
        // 设置面包屑
        const root: ActivatedRoute = this.activatedRoute.root;
        console.log('=== janine.树的的根路由', root);
        this.breadcrumbs = this.getBreadcrumbs(root);
      });
  }

  /**
   * 返回表示面包屑的IBreadcrumb对象的数组
   */
  private getBreadcrumbs(route: ActivatedRoute, url: string = '', breadcrumbs: IBreadcrumb[] = []): IBreadcrumb[] {
    const ROUTE_DATA_BREADCRUMB = 'breadcrumb';

    // 得到子路由
    const children: ActivatedRoute[] = route.children;
    console.log('=== janine.有多少子路由 ===', children);

    // 如果没有子路由返回
    if (children.length === 0) {
      console.log('=== janine.没有子路由是 ===', breadcrumbs);
      return breadcrumbs;
    }

    // 遍历每个子元素
    for (const child of children) {
      // 验证主路由
      if (child.outlet !== PRIMARY_OUTLET) {
        continue;
      }

      // 验证路由上指定的自定义数据属性'breadcrumb'
      if (!child.snapshot.data.hasOwnProperty(ROUTE_DATA_BREADCRUMB)) {
        return this.getBreadcrumbs(child, url, breadcrumbs);
      }

      // 获取路由的URL进行分割
      const routeURL: string = child.snapshot.url.map(segment => segment.path).join('/');
      // append route URL to URL 追加路由的url到url
      if (routeURL) {
        console.log('=== janine.routeURL ===', routeURL);
        url += `/${routeURL}`;
      }

      // 添加面包屑
      const breadcrumb: IBreadcrumb = {
        label: child.snapshot.data[ROUTE_DATA_BREADCRUMB],
        params: child.snapshot.params,
        url: url
      };
      // 此处的 component 如果为 undefined,可能是因为懒加载,在查找时,没有找到 component 的值,
      // 所以当 component 为 undefined 的时候,就会又往数组里再追加一次,会重复
      if (child.component) {
        breadcrumbs.push(breadcrumb);
      }

      console.log('=== janine.breadcrumbs === ', breadcrumb);

      // 递归
      return this.getBreadcrumbs(child, url, breadcrumbs);
    }
  }

}

4. 知识点

(1) filter

import { filter } from 'rxjs/operators';

rxjs 的 filter() 方法,是 Angular6的,不是其他版本,如果版本不对,会出错! 对应的使用步骤如下:

ngOnInit() {
    // 订阅NavigationEnd事件
    this.router.events.pipe(filter(event => event instanceof NavigationEnd))
      .subscribe(event => {
        // 设置面包屑
        const root: ActivatedRoute = this.activatedRoute.root;
        console.log('=== janine.树的的根路由', root);
        this.breadcrumbs = this.getBreadcrumbs(root);
      });
  }

(2)NavigationEnd, Params, PRIMARY_OUTLET

Router 和 ActivatedRoute 就不说了,这是 Angular 路由最常见的。讲一下 NavigationEnd, Params, PRIMARY_OUTLET。

  • NavigationEnd:表示当导航 成功结束 时(当从一个路径到另一个导航已经完成时)触发的事件。
  • Params:用来设置 IBreadcrumb 接口的 params 的类型为 Params。params 为非必需,其他两个为必需的。
interface IBreadcrumb {
  label: string;
  params: Params;
  url: string;
}
  • PRIMARY_OUTLET:一个常量 primary

(3) 添加面包屑

代码中,有一段是将路由追加到数组中。这里会有一个关于懒加载的问题,代码注释里已经说明了。

如果有懒加载就得加个判读 child.component 是否 为 undefined ,只有不是 undefined 时才能向数组中追加,否则会重复(这里可以去掉判断,自己 debugger 一下,关注一下 component 值的变化,和数组追加后数组值的变化情况)。

如果没有懒加载,可以不对 breadcrumbs.push(breadcrumb); 做判断!

// 添加面包屑
const breadcrumb: IBreadcrumb = {
    label: child.snapshot.data[ROUTE_DATA_BREADCRUMB],
    params: child.snapshot.params,
    url: url
};
// 此处的 component 如果为 undefined,可能是因为懒加载,在查找时,没有找到 component 的值,
// 所以当 component 为 undefined 的时候,就会又往数组里再追加一次,会重复
if (child.component) {
    breadcrumbs.push(breadcrumb);
}

5. 路由信息配置: data: { breadcrumb: 'xxx' }

export const routes = [
    {
        // 路由为空时,自动重定向到/home
        path: '',
        redirectTo: '/home/basic',
        pathMatch: 'full',
    },
    {
        path: 'home', component: HomeComponent,
        children: [
            {
                path: 'basic', loadChildren: './basic/basic.module#BasicModule',
                data: { breadcrumb: '基础' }
            },
            ...
            {
                path: 'server', loadChildren: './server/server.module#ServerModule',
                data: { breadcrumb: '服务' }
            }
        ]
    },
];

如果模块中,还有子路由,也是同样配置!

6. 效果图:

路由面包屑.gif

附录

源码地址:https://github.com/Janine-ZN/ng-basic (重点:breadcrumb.component.ts 和 routes.ts,还有一些模块中的路由配置)

参考的博客是针对 Angular2 的,而且不适用于路由懒加载,如果有路由懒加载的地方页面可能会出重复的路由。

博客参考地址:
https://yfblog.cn/angular2-breadcrumb-using-router.html


关注博主公众号,更多精彩等着你!!!


公众号
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • 一:路由基础 什么是路由: 在web开发中,路由的概念由来已久,简而言之,就是利用URL的唯一性来指定特定的事物,...
    真的稻城阅读 5,935评论 2 7
  • 一.课程简介 (注意:这里的AngularJS指的是2.0以下的版本) AngularJS的优点: 模板功能强大丰...
    壹点微尘阅读 859评论 0 0
  • 主题: 导航栏和一级菜单面包屑 导航栏 导航栏作为通用组件,把它放在conponets文件夹下并新起一个文件夹ma...
    酸萝卜阅读 6,209评论 3 1
  • 路由与导航 在用户使用应用程序时,Angular 的路由器能让用户从一个视图导航到另一个视图。 概览 Angula...
    chrisghb阅读 4,036评论 0 0
  • 一、具体需求: 1. 页面布局 左侧导航,右侧侧边辅助菜单,中间主业务界面;左侧导航是根据用户权限动态生成的。 2...
    环零弦阅读 8,602评论 0 3