GVKun编程网logo

angular – 对子路由的RouterLinkActive都是false(angular 路由传值)

14

对于想了解angular–对子路由的RouterLinkActive都是false的读者,本文将提供新的信息,我们将详细介绍angular路由传值,并且为您提供关于Angular2RouterLink

对于想了解angular – 对子路由的RouterLinkActive都是false的读者,本文将提供新的信息,我们将详细介绍angular 路由传值,并且为您提供关于Angular 2 RouterLink for Select、Angular 4.x Router Link Directives、Angular 7 routerLink指令警告’在Angular zone外部触发导航’、Angular Router 框架中 DefaultUrlSerializer 的使用方法介绍的有价值信息。

本文目录一览:

angular – 对子路由的RouterLinkActive都是false(angular 路由传值)

angular – 对子路由的RouterLinkActive都是false(angular 路由传值)

我有以下儿童路线:

{ path: '',component: LoginSingupComponent,children: [
    { path: 'login',component: LoginComponent },{ path: 'singup',component: SingupComponent },]
},

导航到/ login或/ singup工作正常(加载了正确的组件).

这是LoginSingupComponent的摘录

<nav md-tab-nav-bar>
  <a md-tab-link routerLink="/login" routerLinkActive [routerLinkActiveOptions]="{exact: true}" #rla="routerLinkActive" [active]="rla.isActive">Entrar {{rla.isActive}}</a>
  <a md-tab-link routerLink="/singup" routerLinkActive [routerLinkActiveOptions]="{exact: true}" #rla="routerLinkActive" [active]="rla.isActive">Criar uma conta{{rla.isActive}}</a>
</nav>

当打开/登录时,所有rla.isActive == false,当打开/ singup时,所有rla.isActive == true

尝试使用和不使用exact:true

解决方法

试试这样:

<nav md-tab-nav-bar>
    <a md-tab-link [routerLink]="['/']" routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}">Home</a>
    <a md-tab-link [routerLink]="['/login']" routerLinkActive="active">Login</a>
    <a md-tab-link [routerLink]="['/singup']" routerLinkActive="active">Signup</a>
</nav>

Angular 2 RouterLink for Select

我想使用页面上的select元素创建导航.在锚标记上使用RouterLink指令很简单,但选择下拉列表是否相同?或者,当我的选择发生变化时,我是否需要在我的组件上创建自己的导航方法?

<a [routerLink]="[location]">Location</a>

<select (change)="navigate($event.target.value)">
    <option>--Select Option--</option>
    <option [value]="[location]">Location</option>
</select>

我正在寻找这样的东西:

<select>
    <option>--Select Option--</option>
    <option [routerLink]="[location]">Location</option>
</select>

解决方法

是的,您需要在组件内部创建导航方法并将其绑定到选择控件的(更改)事件,然后使用注入的路由器在该方法内部进行导航.

如果您查看Angular 2路由器source code for RouterLink指令,您将看到它也在场景后面使用router.navigate导航到目标路由.它不适用于您的select控件,因为select没有ClickLink指令捕获的click事件,如下所示:

// ** Code below is copied from Angular source code on GitHub. **
@HostListener("click")
  onClick(): boolean {
    // If no target,or if target is _self,prevent default browser behavior
    if (!isstring(this.target) || this.target == '_self') {
      this._router.navigate(this._commands,this._routeSegment);
      return false;
    }
    return true;
  }

Angular 4.x Router Link Directives

RouterLink 指令简介

RouterLink 指令可以让你链接到应用程序的特定部分。若链接是静态的,我们可以按照以下的方式,来使用该指令:

<a routerLink="/user/bob">link to user component</a>

如果你需要使用动态值生成链接地址,你可以传递一个路径片段 (segments) 的数组,然后再传递每个段的参数。例如使用 [''/team'', teamId, ''user'', userName, {details: true}] 数组,意味着我们想要生成一个链接到 /team/11/user/bob;details=true

多个静态段 (segments) 能够被合并为一个,例如 [''/team/11/user'', userName, {details: true}]

第一个路径片段可以以 /./../ 开头:

  • 如果以 / 开头,路由将从根路由开始查找

  • 如果以 ./ 开头或没有使用 / ,则路由将从当前激活路由的子路由开始查找

  • 如果以 ../ 开头,路由往上一级查找

你可以使用以下方式设置查询参数和片段 (fragment):

<a [routerLink]="[''/user/bob'']" [queryParams]="{debug: true}" fragment="education">
   link to user component
</a>

RouterLink 指令将基于以上设定的输入参数,生成如下链接:/user/bob#education?debug=true 。此外我们可以通过 queryParamsHandling 属性来声明如何处理查询参数,可用的选项是:

  • merge - 合并已有的 queryParams 到当前的 queryParams

  • preserve - 保存当前的 queryParams

  • default ('''') - 仅使用查询参数

具体使用示例如下:

<a [routerLink]="[''/user/bob'']" [queryParams]="{debug: true}" queryParamsHandling="merge">
    link to user component
</a>

RouterLink 指令详解

RouterLink 指令定义

@Directive({selector: '':not(a)[routerLink]''})

RouterLink 指令输入属性

// 设置URL相关的查询参数
@Input() queryParams: {[k: string]: any};

// 设置URL上的hash fragment
@Input() fragment: string; 

// 设置查询参数处理方式:merge、preserve 、default 
@Input() queryParamsHandling: QueryParamsHandling; 

// 设置是否保留fragment
@Input() preserveFragment: boolean;

// 设置页面导航时,是否把新的状态添加到历史记录中
@Input() skipLocationChange: boolean;

// 设置页面导航的同时,是否替换历史记录中的当前状态
@Input() replaceUrl: boolean;
 
// 设置commands参数信息,如:[''/user/bob'']
@Input()
set routerLink(commands: any[]|string) {
    if (commands != null) {
      this.commands = Array.isArray(commands) ? commands : [commands];
    } else {
      this.commands = [];
    }
}

RouterLink 指令绑定

事件绑定

// 监听RouterLink指令宿主元素的click事件,进行页面切换
@HostListener(''click'')
onClick(): boolean {
  const extras = {
     skipLocationChange: attrBoolValue(this.skipLocationChange),
     replaceUrl: attrBoolValue(this.replaceUrl),
   };
   this.router.navigateByUrl(this.urlTree, extras);
   return true;
}

// 转化设置的属性值为bool值
function attrBoolValue(s: any): boolean {
  return s === '''' || !!s;
}

RouterLink 类的构造函数

export class RouterLink { 
    constructor(
      private router: Router, 
      private route: ActivatedRoute,
      @Attribute(''tabindex'') tabIndex: string, 
      renderer: Renderer, el: ElementRef) {
        if (tabIndex == null) {
          renderer.setElementAttribute(el.nativeElement, ''tabindex'', ''0'');
        }
    }
}

@Attribute()

@Attribute(''attributeName'') 装饰器:用于获取指令宿主元素上 attributeName 属性名对应的属性值。

tabindex

tabindex 属性规定元素的 tab 键控制次序 (当 tab 键用于导航时)。

以下元素支持 tabindex 属性:<a>, <area>, <button>, <input>, <object>, <select> 以及 <textarea>

tabindex 语法:

<element tabindex="number"> <!-- number:规定元素的 tab 键控制次序 (1是第一个)-->

RouterLink 类的属性

// 用于保存commands参数信息
private commands: any[] = [];

// 标识是否保存查询参数,4.0.0版本后用queryParamsHandling代替
private preserve: boolean;

RouterLink 类的方法

// 获取routerLink上配置信息对应的UrlTree
get urlTree(): UrlTree {
    return this.router.createUrlTree(this.commands, {
      relativeTo: this.route,
      queryParams: this.queryParams,
      fragment: this.fragment,
      preserveQueryParams: attrBoolValue(this.preserve),
      queryParamsHandling: this.queryParamsHandling,
      preserveFragment: attrBoolValue(this.preserveFragment),
    });
}

// angular\packages\router\src\router.ts
// 创建UrlTree
createUrlTree(
    commands: any[],
    {relativeTo, queryParams, fragment, 
     preserveQueryParams, queryParamsHandling,preserveFragment}: 
      NavigationExtras = {}): UrlTree {
    if (isDevMode() && preserveQueryParams && <any>console && <any>console.warn) {
      console.warn(''preserveQueryParams is deprecated, use queryParamsHandling instead.'');
    }
    const a = relativeTo || this.routerState.root;
    const f = preserveFragment ? this.currentUrlTree.fragment : fragment;
    let q: Params|null = null;
    // 根据queryParamsHandling属性值,处理查询参数
    if (queryParamsHandling) {
      switch (queryParamsHandling) {
        case ''merge'':
          q = {...this.currentUrlTree.queryParams, ...queryParams};
          break;
        case ''preserve'':
          q = this.currentUrlTree.queryParams;
          break;
        default:
          q = queryParams || null;
      }
    } else {
      q = preserveQueryParams ? this.currentUrlTree.queryParams : queryParams || null;
    }
    return createUrlTree(a, this.currentUrlTree, commands, q !, f !);
}

RouterLinkWithHref 指令详解

RouterLinkWithHref 指令定义

@Directive({selector: ''a[routerLink]''})

RouterLinkWithHref 指令输入属性

// 设置a标签target的值
@Input() target: string;

// 设置URL相关的查询参数
@Input() queryParams: {[k: string]: any};

// 设置URL上的hash fragment
@Input() fragment: string;

// 设置查询参数处理方式:merge、preserve 、default 
@Input() queryParamsHandling: QueryParamsHandling;

// 设置是否保留fragment
@Input() preserveFragment: boolean;

// 设置页面导航时,是否把新的状态添加到历史记录中
@Input() skipLocationChange: boolean;

// 设置页面导航的同时,是否替换历史记录中的当前状态
@Input() replaceUrl: boolean;

// 设置commands信息,如:[''/user/bob'']
@Input()
set routerLink(commands: any[]|string) {
    if (commands != null) {
      this.commands = Array.isArray(commands) ? commands : [commands];
    } else {
      this.commands = [];
    }
}

RouterLinkWithHref 指令绑定

属性绑定

@HostBinding(''attr.target'') @Input() target: string;
@HostBinding() href: string;

<a> 标签定义超链接,用于从一个页面链接到另外一个页面。<a> 标签中有两个重要的属性:

  • href - 规定链接指向的页面的 URL 地址。如果不使用 href 属性,则不可以使用如下属性:download, media, rel, target 以及 type 属性。

  • target - 规定链接的页面在浏览器窗口中的打开方式,它的参数值主要有:

    • _blank - 在新的浏览器窗口中载入目标文档。

    • _parent - 这个目标使得文档载入父窗口或者包含来超链接引用的框架的框架集。如果这个引用是在窗口或者在顶级框架中,那么它与目标 _self 等效。

    • _self - 这个目标的值对所有没有指定目标的 <a> 标签是默认目标,它使得目标文档载入并显示在相同的框架或者窗口中作为源文档。这个目标是多余且不必要的,除非和文档标题 <base> 标签中的 target 属性一起使用。

    • _top - 这个目标使得文档载入包含这个超链接的窗口,用 _top 目标将会清除所有被包含的框架并将文档载入整个浏览器窗口。

事件绑定

// 监听RouterLink指令宿主元素的click事件,进行页面切换
@HostListener(''click'', [''$event.button'', ''$event.ctrlKey'', ''$event.metaKey''])
  onClick(button: number, ctrlKey: boolean, metaKey: boolean): boolean {
    if (button !== 0 || ctrlKey || metaKey) {
      return true;
    }

    if (typeof this.target === ''string'' && this.target != ''_self'') {
      return true;
    }

    const extras = {
      skipLocationChange: attrBoolValue(this.skipLocationChange),
      replaceUrl: attrBoolValue(this.replaceUrl),
    };
    this.router.navigateByUrl(this.urlTree, extras);
    return false;
}

MouseEvent 表示用户与指针设备 (如鼠标) 交互时发生的事件,常见的事件包括:click、dblclick、mouseup 与 mousedown 事件。其中 MouseEvent 对象中包含一个 button 属性,用于表示用户按下的鼠标按键,可能的属性值如下:

  • 0 - 主按键被按下,通常指鼠标左键。

  • 1 - 辅助按键被按下,通常指鼠标滚轮。

  • 2 - 次按键被按下,通常指鼠标右键。

  • 3 - 第四个按钮被按下,通常指浏览器后退按钮。

  • 4 - 第五个按钮被按下,通常指浏览器的前进按钮。

对于配置为左手使用的鼠标,按键操作将正好相反。此种情况下,从右至左读取值。在上面示例代码中,我们还访问了 MouseEvent 对象的 ctrlKeymetaKey 属性,此外除了这两个属性外 MouseEvent 对象中还包含 altKeyshiftKey 属性。这些属性的相关说明如下:

  • MouseEvent.ctrlKey - 当鼠标事件触发时,如果 control 键被按下,则返回 true。

  • MouseEvent.metaKey - 当鼠标事件触发时,如果 (Window - ,Mac - ⌘ Command ) 键被按下,则返回 true。

  • MouseEvent.altKey - 当鼠标事件触发的时候,如果 (Window - alt ,Mac - Option ) 键被按下,返回true。

  • MouseEvent.shiftKey - 当鼠标事件触发时,如果 shift 键被按下,则返回 true。

若按下 ctrlKey ,再点击 <a> 标签,则会使用当前的 URL 地址,新建一个新的 tab 页。若按下 metaKey ,再点击 <a> 标签,则会重新刷新当前页。因此在 onClick() 方法中,才会执行相应的判断。

RouterLinkWithHref 指令生命周期

ngOnChanges()

// 输入属性发生变化时,更新a标签href属性
ngOnChanges(changes: {}): any { 
  this.updateTargetUrlAndHref();
}

ngOnDestroy()

// 指令销毁时,取消路由事件的订阅
ngOnDestroy(): any { 
  this.subscription.unsubscribe(); 
}

RouterLinkWithHref 类的构造函数

export class RouterLinkWithHref implements OnChanges, OnDestroy {
  constructor(
      private router: Router, 
      private route: ActivatedRoute,
      private locationStrategy: LocationStrategy) {
      // 订阅路由事件,当页面切换成功后更新a标签的href属性
      this.subscription = router.events.subscribe(s => {
      if (s instanceof NavigationEnd) {
        this.updateTargetUrlAndHref();
      }
    });
  }
}

RouterLinkWithHref 类的属性

// 用于保存commands参数信息
private commands: any[] = [];

// 用于保存取消订阅路由事件订阅的Subscription对象
private subscription: Subscription;

// 标识是否保存查询参数,4.0.0版本后用queryParamsHandling代替
private preserve: boolean;

RouterLinkWithHref 类的方法

// 获取routerLink上配置信息对应的UrlTree
get urlTree(): UrlTree {
    return this.router.createUrlTree(this.commands, {
      relativeTo: this.route,
      queryParams: this.queryParams,
      fragment: this.fragment,
      preserveQueryParams: attrBoolValue(this.preserve),
      queryParamsHandling: this.queryParamsHandling,
      preserveFragment: attrBoolValue(this.preserveFragment),
    });
}

// 更新a标签href属性值
private updateTargetUrlAndHref(): void {
    this.href = this.locationStrategy
      .prepareExternalUrl(this.router.serializeUrl(this.urlTree));
}

RouterLinkActive 指令简介

RouterLinkActive 指令允许你在链接的路由变为活动状态时向元素添加 CSS 类。请看一下以下示例:

<a routerLink="/user/bob" routerLinkActive="active-link">Bob</a>

当 URL 地址是 /user/user/bob 时,active-link 类将会被添加到 <a> 标签上。如果 URL 发生变化,则 active-link 类将自动从 <a> 标签上移除。你也可以一次性添加多个类,具体如下:

<a routerLink="/user/bob" routerLinkActive="class1 class2">Bob</a>
<a routerLink="/user/bob" [routerLinkActive]="[''class1'', ''class2'']">Bob</a>

在应用 routerLinkActive 指令时,你也可以通过 routerLinkActiveOptions 参数,来配置 URL 的匹配方式,具体如下:

<a routerLink="/user/bob" routerLinkActive="active-link" 
  [routerLinkActiveOptions]="{exact: true}">Bob</a>

当配置了 {exact: true} 参数,仅当 URL 地址完全匹配时,active-link 类才会被添加到 <a> 标签上。此外你可以将 RouterLinkActive 实例分配给模板变量,并直接检查指令的 isActive 状态:

<a routerLink="/user/bob" routerLinkActive #rla="routerLinkActive">
    Bob {{ rla.isActive ? ''(already open)'' : ''''}}
</a>

最后,你也可以将 RouterLinkActive 指令应用于 RouterLink 的父级元素。具体示例如下:

<div routerLinkActive="active-link" [routerLinkActiveOptions]="{exact: true}">
  <a routerLink="/user/jim">Jim</a>
  <a routerLink="/user/bob">Bob</a>
</div>

在上面示例中,当 URL 的地址为 /user/jim/user/bob 时,active-link 类会被添加到对应的 <div> 元素上。

RouterLinkActive 指令详解

RouterLinkActive 指令定义

@Directive({
  selector: ''[routerLinkActive]'',
  exportAs: ''routerLinkActive'',
})

RouterLinkActive 指令输入属性

// 设置处于激活状态时,宿主元素上应用的class信息
@Input()
set routerLinkActive(data: string[]|string) {
  const classes = Array.isArray(data) ? data : data.split('' '');
  this.classes = classes.filter(c => !!c);
}

// 设置URL地址的匹配方式
@Input() routerLinkActiveOptions: {exact: boolean} = {exact: false};

RouterLinkActive 指令生命周期

ngAfterContentInit()

// 订阅RouterLink或RouterLinkWithHref集合的changes对象,从而自动更新宿主元素的class信息
ngAfterContentInit(): void {
    this.links.changes.subscribe(_ => this.update());
    this.linksWithHrefs.changes.subscribe(_ => this.update());
    this.update();
}

ngOnChanges()

// 输入属性变化时,更新宿主元素的class信息
ngOnChanges(changes: SimpleChanges): void { this.update(); }

ngOnDestroy()

// 指令销毁时,取消路由事件的订阅
ngOnDestroy(): void { this.subscription.unsubscribe(); }

RouterLinkActive 类的构造函数

export class RouterLinkActive implements OnChanges,
    OnDestroy, AfterContentInit {
      constructor(
        private router: Router, 
        private element: ElementRef, 
        private renderer: Renderer,
          private cdr: ChangeDetectorRef) {
         // 订阅路由事件,当页面切换成功后更新宿主元素上的class信息
          this.subscription = router.events.subscribe(s => {
            if (s instanceof NavigationEnd) {
              this.update();
            }
    });
  }
}

RouterLinkActive 类的属性

// 获取RouterLink集合
@ContentChildren(RouterLink, {descendants: true}) links: QueryList<RouterLink>;

// 获取RouterLinkWithHref集合
@ContentChildren(RouterLinkWithHref, {descendants: true})
  linksWithHrefs: QueryList<RouterLinkWithHref>;
  
// 激活状态的样式列表
private classes: string[] = [];

// 用于保存取消订阅路由事件订阅的Subscription对象
private subscription: Subscription;

// 标识是否处于激活状态
private active: boolean = false;

RouterLinkActive 类的方法

// 获取激活状态
get isActive(): boolean { return this.active; }

// 更新宿主元素的class信息
private update(): void {
    if (!this.links || !this.linksWithHrefs || !this.router.navigated) return;
    const hasActiveLinks = this.hasActiveLinks();

    // react only when status has changed to prevent unnecessary dom updates
    if (this.active !== hasActiveLinks) {
      this.classes.forEach(
          c => this.renderer.setElementClass(this.element.nativeElement, c, hasActiveLinks));
      Promise.resolve(hasActiveLinks).then(active => this.active = active);
    }
}

// 判断是否是激活的链接
private isLinkActive(router: Router): (link: (RouterLink|RouterLinkWithHref)) => boolean {
  return (link: RouterLink | RouterLinkWithHref) =>
           router.isActive(link.urlTree, this.routerLinkActiveOptions.exact);
}

// 判断RouterLink或RouterLinkWithHref集合中是否含有激活的链接
private hasActiveLinks(): boolean {
  return this.links.some(this.isLinkActive(this.router)) ||
      this.linksWithHrefs.some(this.isLinkActive(this.router));
}

Angular 7 routerLink指令警告’在Angular zone外部触发导航’

Angular 7 routerLink指令警告’在Angular zone外部触发导航’

我正在努力使用Angular框架来使我的应用程序顺利运行,但我无法解决路由问题.
我有一个顶级AppComponent和app-routing.module.ts,它通过我的自定义SlideMenuComponent管理导航.我简化的AppComponent html模板:

<app-slide-menu [buttons]="menuButtons"></app-slide-menu>
<router-outlet></router-outlet>

我的SlideMenuComponent具有以下html作为其核心:

<nav><div *ngFor="let button of buttons">
    <a routerLink="{{button.routerLink}}"
    >{{button.name}}</a>
</div></nav>

用户可以通过此幻灯片菜单导航到“/ courses”,该菜单由CoursesComponent监督,该菜单将指向从服务器检索的特定CourseComponents的链接分页.这些组件驻留在他们自己的courses.module.ts模块中,他们自己的课程是routing.module.ts.但是,当我点击任何这些链接时,我会在Angular区域外触发导航,你是否忘记调用’ngzone.run()’?控制台警告,没有为打开的CourseCompontent调用ngOnInit(),并且它不会更新,直到我单击页面上的任何按钮.我通过router.navigate()手动导航时通过将此任务转发到ngzone.runTask(router.navigate())来解决此问题,但为什么会发生锚标记和routerLink direcrives?
这是我的CoursesComponent代码摘录:

<nav><ul>
        <li *ngFor="let course of api.data | paginate: {
            currentPage: currentPage,itemsPerPage: limit,totalItems: api.total
        }">
           <a
               [routerLink]="course._id"
               [queryParams]="{ page: '1',limit: '5' }"
           >
            {{course.name}} ({{course.description}})
           </a>
        </li>
</ul></nav>

用来证明这个问题的gif:

   

enter image description here

解决方法

它会发现一个错误,尝试将其作为一种解决方法

constructor(private ngzone: ngzone,private router: Router) {}

public navigate(commands: any[]): void {
    this.ngzone.run(() => this.router.navigate(commands)).then();
}

Angular Router 框架中 DefaultUrlSerializer 的使用方法介绍

Angular Router 框架中 DefaultUrlSerializer 的使用方法介绍

DefaultUrlSerializer 是 Angular 路由 (Router) 模块中的一个核心类,负责解析和序列化 URL。Angular 的路由系统是非常复杂且功能强大的,其设计旨在简化单页应用 (SPA) 的导航流程。而 DefaultUrlSerializer 在其中扮演着关键角色,确保 URL 能够正确地解析和序列化,从而使路由配置和导航得到顺利执行。

DefaultUrlSerializer 的基本功能

DefaultUrlSerializer 的主要职能是将 URL 字符串解析为 UrlTree,以及将 UrlTree 序列化为 URL 字符串。这两个操作分别对应 parseserialize 两个方法。

  • parse(url: string): UrlTree:将一个 URL 字符串解析成一个 UrlTree 对象。
  • serialize(tree: UrlTree): string:将 UrlTree 对象序列化为一个 URL 字符串。

UrlTree 是 Angular 中用来表示路由树结构的对象,它包含了有关导航的所有信息,例如路径片段、查询参数、或者 URL 片段的层次结构。

使用场景

DefaultUrlSerializer 在实际开发中有多个使用场景。例如,您可能会遇到需要自定义解析 URL 或序列化 URL 的需求,比如在 URL 中进行特殊字符编码,处理复杂的查询参数,或者支持某种自定义的路由格式。在这些情况下,可以使用 DefaultUrlSerializer 进行扩展或者自定义实现。

示例解析与序列化

示例 1:基本的 URL 解析

import { DefaultUrlSerializer, UrlTree } from `@angular/router`;

const url = `/path/to/resource?query=123`;
const serializer = new DefaultUrlSerializer();

const tree: UrlTree = serializer.parse(url);
console.log(tree);

在这个示例中,我们创建了一个 DefaultUrlSerializer 实例,并解析了一个包含查询参数的 URL。解析结果中的 UrlTree 结构可以被进一步用于导航或其他操作。

示例 2:URL 序列化

import { DefaultUrlSerializer, UrlTree, PRIMARY_OUTLET } from `@angular/router`;

const serializer = new DefaultUrlSerializer();
const urlTree: UrlTree = {
  root: {
    segments: [],
    children: {
      [PRIMARY_OUTLET]: [
        { path: `path`, parameters: {} },
        { path: `to`, parameters: {} },
        { path: `resource`, parameters: {} }
      ]
    }
  },
  queryParams: { query: `123` },
  fragment: null
};

const url = serializer.serialize(urlTree);
console.log(url); // 输出: /path/to/resource?query=123

在这个示例中,我们手动构建了一个 UrlTree 对象并使用 DefaultUrlSerializer 将其序列化为字符串 URL。

自定义 DefaultUrlSerializer

如果需要实现自定义的 URL 解析和序列化逻辑,可以通过扩展 DefaultUrlSerializer 来实现。例如,如果需要对 URL 中的某些字符进行特殊处理,比如替换某些字符或者添加自定义的逻辑来解析和生成 URL。

下面展示一个简单的自定义实现:

示例 3:扩展 DefaultUrlSerializer

import { DefaultUrlSerializer, UrlTree } from `@angular/router`;

class CustomUrlSerializer extends DefaultUrlSerializer {
  // 自定义解析 URL 的逻辑
  parse(url: string): UrlTree {
    // 在这里添加自定义逻辑
    url = url.replace(/%XX/g, `XX`);
    return super.parse(url);
  }

  // 自定义序列化 URL 的逻辑
  serialize(tree: UrlTree): string {
    let url = super.serialize(tree);
    // 在这里添加自定义逻辑
    url = url.replace(/XX/g, `%XX`);
    return url;
  }
}

这个 CustomUrlSerializer 继承自 DefaultUrlSerializer,并重写了 parseserialize 方法,以实现 URL 中某些字符的自定义替换。

使用自定义的 URL Serializer

要使用自定义的 URL Serializer,需要在 Angular 应用程序的提供者 (Providers) 中配置它。

示例 4:配置自定义 URL Serializer

import { NgModule } from `@angular/core`;
import { RouterModule } from `@angular/router`;
import { CustomUrlSerializer } from `./custom-url-serializer`; // 引入自定义 URL Serializer

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  providers: [
    { provide: `UrlSerializer`, useClass: CustomUrlSerializer }
  ]
})
export class AppModule {}

在这个示例中,通过 Angular DI 容器提供了自定义的 URL Serializer,从而使其在整个应用程序中生效。

深入解析 DefaultUrlSerializer

DefaultUrlSerializer 实现了一个基于正则表达式的解析器,用于从 URL 字符串中提取路径、查询参数和片段。解析的结果会被转换为 UrlTree 结构。这种设计允许 Angular 对路由URL 进行灵活的处理和优化,使开发者能够充分利用路由系统的各种功能。

以下是 DefaultUrlSerializer 的内部解析和序列化的简化版本:

示例 5:内部解析和序列化逻辑

import { Injectable } from `@angular/core`;
import { UrlTree, UrlSegment, PRIMARY_OUTLET } from `@angular/router`;

@Injectable()
export class DefaultUrlSerializer {
  parse(url: string): UrlTree {
    // 系统化和移除前后的空白字符
    const cleanedUrl = url.trim();

    // 解析路径和片段
    const urlTree = this.parseUrlTree(cleanedUrl);

    // 解析查询参数
    const queryParams = this.parseQueryParams(cleanedUrl);

    // 创建 UrlTree 对象
    const tree: UrlTree = {
      root: urlTree,
      queryParams,
      fragment: this.parseFragment(cleanedUrl)
    };

    return tree;
  }

  serialize(tree: UrlTree): string {
    const segments = this.serializeSegments(tree.root);
    const queryParams = this.serializeQueryParams(tree.queryParams);
    const fragment = tree.fragment ? `#${tree.fragment}` : '''';

    // 组合最终的 URL
    return `${segments}${queryParams}${fragment}`;
  }

  private parseUrlTree(url: string): any {
    // 省略复杂的正则解析逻辑
    return { ... };
  }

  private parseQueryParams(url: string): any {
    // 省略复杂的查询参数解析逻辑
    return { ... };
  }

  private parseFragment(url: string): string | null {
    // 省略复杂的片段解析逻辑
    return null;
  }

  private serializeSegments(tree: any): string {
    // 省略复杂的序列化逻辑
    return ''/path'';
  }

  private serializeQueryParams(queryParams: any): string {
    // 省略复杂的序列化逻辑
    return ''?query=123'';
  }
}

这个代码片段展示了 DefaultUrlSerializer 如何通过多个方法来解析和序列化 URL。虽然细节部分省略,但大致的处理流程展示了 Angular 在处理 URL 时的不同阶段和功能模块。这些方法大多基于正则表达式和字符串操作,可以处理复杂的 URL 结构,包括不同路径片段、查询参数以及 URL 片段。

结论

DefaultUrlSerializer 是 Angular 路由模块的一个核心组件,负责 URL 的解析和序列化操作。通过 DefaultUrlSerializer,Angular 可以将 URL 字符串转换为 UrlTree 对象,以及将 UrlTree 对象转换为字符串 URL。这样一来,整个路由系统得以正常运作,开发者可以灵活地配置和操作路由。

在一些特定的应用场景下,可能会需要自定义 URL 解析和序列化逻辑,比如处理特殊字符、支持自定义格式等。这时,可以通过继承 DefaultUrlSerializer 并重写 parseserialize 方法来实现。此外,在应用程序的提供者配置中注入自定义的 Serializer 类以替代默认实现,使得整个应用程序能够使用自定义的 URL 处理逻辑。

利用这一套机制,可以极大地提升单页应用的导航能力,满足更加复杂和精细的需求,同时保持代码结构的清晰和可维护性。

我们今天的关于angular – 对子路由的RouterLinkActive都是falseangular 路由传值的分享已经告一段落,感谢您的关注,如果您想了解更多关于Angular 2 RouterLink for Select、Angular 4.x Router Link Directives、Angular 7 routerLink指令警告’在Angular zone外部触发导航’、Angular Router 框架中 DefaultUrlSerializer 的使用方法介绍的相关信息,请在本站查询。

本文标签: