【问题标题】:Angular - routerLinkActive and queryParams handlingAngular - routerLinkActive 和 queryParams 处理
【发布时间】:2018-01-09 02:03:47
【问题描述】:

2021 年 3 月更新

Angular 团队终于为此合并了 PR,您可以查看https://github.com/angular/angular/pull/40303 了解更多详情。

要使用它,只需输入

<div routerLinkActive="active-link" [routerLinkActiveOptions]="options">
</div>

options 将具有 IsActiveMatchOptions 的形状

export declare interface IsActiveMatchOptions {
    fragment: 'exact' | 'ignored';
    matrixParams: 'exact' | 'subset' | 'ignored';
    paths: 'exact' | 'subset';
    queryParams: 'exact' | 'subset' | 'ignored';
}

或者简单地接受一个布尔值exact

{
   exact: boolean
}

原始问题

我在 Angular 中使用 routerLink,如下所示

<li routerLinkActive="active">
    <a [routerLink]="['/view', 10]"                 
       [queryParams]="{'offset': 0, 'numberOfItems': 100}" 
       queryParamsHandling="merge">
        <div>View</div>
        <div><span class="badge" [innerHtml]="viewCount"></span></div>
    </a>
</li>

所以当 URL 看起来像这样时,.active 类被添加到 li 标签中

/view/10?offset=0&numberOfItems=100

如果 URL 更改为 offsetnumberOfItems 为不同的值,则 .active 类将被删除,例如。

/view/10?offset=0&numberOfItems=120

我浏览了angular docs 并设法通过添加另一个 routerLink 使其工作,但将其隐藏如下。

<li routerLinkActive="active">
    <a [routerLink]="['/view', 10]"                 
       [queryParams]="{'offset': 0, 'numberOfItems': 100}" 
       queryParamsHandling="merge">
        <div>View</div>
        <div><span class="badge" [innerHtml]="viewCount"></span></div>
    </a>
    <a [routerLink]="['/view', 10]" style="display:none;">                
        <div><span class="badge" [innerHtml]="viewCount"></span></div>
    </a>
</li>

似乎上述方法有点小技巧。当路由器参数带有可选查询参数时,我可以设置任何配置以使 routerLinkActive 工作吗?

【问题讨论】:

  • 只是在这里探索选项:是否有必要在&lt;a&gt; 标签中输入查询参数值(偏移量 = 0,项目 = 100)?如果这是默认值,不应该在目标组件本身内设置它们吗?在这种情况下,您只需要一个&lt;a&gt;
  • 以我目前的架构,是必须的。因为我用相同的组件配置了 2 个不同的路由并解析。一条路线需要这些参数,另一条路线不需要。然后当 resolve guard 调用时,我将使用参数来相应地检索数据。
  • 我刚刚检查了源代码。它正在比较确切的 URL,所以不,没有配置来选择退出参数。

标签: angular angular-router


【解决方案1】:

我遇到了同样的问题,但根据 https://github.com/angular/angular/issues/13205 看起来这是设计使然

vsavkin 是路由器创建者。

【讨论】:

  • 感谢您的链接。我们的网络应用程序仍然存在我在问题本身中提到的小技巧。我可能会根据您链接上的答案之一对其进行更改。
  • 是的,有些人提供了解决方法,但我切换回了可选的路由器参数
【解决方案2】:

您可能会发现这很有帮助 - 扩展 RouterLinkActive - 如果一个项目包含一个字符串,则它被“选中”...

import { Directive, Input, OnChanges, ElementRef, Renderer2, ChangeDetectorRef, SimpleChanges, Injector, AfterContentInit } from '@angular/core';
import { Router,RouterLinkActive, RouterLink, RouterLinkWithHref } from '@angular/router';


@Directive({
  selector: '[routerLinkActiveQS]',
  exportAs: 'routerLinkActiveQS'
})
export class RouterLinkQsactiveDirective extends RouterLinkActive implements OnChanges, AfterContentInit
 {

  @Input() 
  set routerLinkActiveQS(data: string[]|string) {
    (<any>this).routerLinkActive = data;
  }

  @Input() routerLinkActiveQSContains : string;

  constructor ( injector: Injector ) {
    super ( injector.get(Router),injector.get(ElementRef),injector.get(Renderer2),injector.get(ChangeDetectorRef));
    (<any>RouterLinkQsactiveDirective.prototype).isLinkActive = this.MyisLinkActive;
  }

  ngOnChanges(changes: SimpleChanges): void {
    super.ngOnChanges(changes); 
  }

  ngAfterContentInit(): void {
    super.ngAfterContentInit();
  }

  private MyisLinkActive(router: Router): (link: (RouterLink|RouterLinkWithHref)) => boolean {
    const result = (link: RouterLink | RouterLinkWithHref) => {
      let resultInsde = router.isActive(link.urlTree, this.routerLinkActiveOptions.exact);
      resultInsde = resultInsde || router.url.includes ( this.routerLinkActiveQSContains );
      return resultInsde;
    }
    return result;
  }

}

【讨论】:

  • 嗨,Doug,这适用于 Angular 10 吗?我在我的应用程序中尝试了此代码,但它不起作用。似乎当前的 RouterLinkActiveDirective 不包含名为 isLinkActive 的方法...
  • @MatterOfFact - 我不这么认为,当我升级到 9 时,我认为它由于基类中不兼容的注入/签名而损坏,我已经涉足路由器覆盖/扩展多年并且发现每当你做的事情太低级时,它通常会在下一个版本中中断....
【解决方案3】:

该解决方案适用于 Angular 11。将链接设置为活动,无论查询参数如何(仅比较段/路径)。

import * as _ from 'lodash';

import {
  AfterContentInit,
  ChangeDetectorRef,
  Directive,
  ElementRef, Input,
  OnChanges,
  OnDestroy,
  Optional,
  Renderer2, SimpleChanges
} from '@angular/core';
import { Router, RouterLink, RouterLinkActive, RouterLinkWithHref } from '@angular/router';

@Directive({
  selector: '[rcRouterLinkActive]',
  exportAs: 'rcRouterLinkActive',
})
export class RcRouterLinkActiveDirective extends RouterLinkActive  implements OnChanges, OnDestroy, AfterContentInit {
  @Input()
  set rcRouterLinkActive(data: string[]|string) {
    const classes = Array.isArray(data) ? data : data.split(' ');
    (<any>this).classes = classes.filter(c => !!c);
  }

  constructor(
    router: Router,
    element: ElementRef,
    renderer: Renderer2,
    cdr: ChangeDetectorRef,
    @Optional() link?: RouterLink,
    @Optional() linkWithHref?: RouterLinkWithHref
  ) {
    super(router, element, renderer, cdr, link, linkWithHref);
    (<any>RcRouterLinkActiveDirective).prototype.isLinkActive = this.isRcLinkActive;
  }

  /**
   * this method sets the link as active regardless of query params
   * @param router
   * @private
   */
  private isRcLinkActive(router: Router): (link: (RouterLink|RouterLinkWithHref)) => boolean {
    return (link: RouterLink|RouterLinkWithHref) =>{
      const linkPath = '/' + link.urlTree.root.children.primary.segments.join('/');

      return router.isActive(link.urlTree, this.routerLinkActiveOptions.exact) ||
        _.startsWith(router.url, linkPath);
    }
  }

  ngOnChanges(changes: SimpleChanges) {
    super.ngOnChanges(changes);
  }

  ngOnDestroy() {
    super.ngOnDestroy();
  }

  ngAfterContentInit() {
    super.ngAfterContentInit();
  }
}

用法(作为标准 angular 的 routerLinkActive 工作):

<a ... rcRouterLinkActive="active" ...>Link text</a>

【讨论】:

    猜你喜欢
    • 2018-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多