注意:这里有许多不同的答案,大多数在某个时期是有效的。事实上,随着Angular团队对路由器的改变,工作原理也发生了多次变化。最终将成为Angular路由器的Router 3.0版本打破了许多这些解决方案,但它提供了一个非常简单的解决方案。从RC.3开始,首选的解决方案是使用[routerLinkActive],如下所示。

在Angular应用程序中(当前在2.0.0 beta版中)。当我写这篇文章时,0发布),你如何确定当前活动的路由是什么?

我正在开发一个使用Bootstrap 4的应用程序,我需要一种方法来标记导航链接/按钮为活动时,他们的相关组件显示在<router-output>标签。

我意识到,当单击其中一个按钮时,我可以自己维护状态,但这不能涵盖进入同一路由的多条路径的情况(比如主导航菜单和主组件中的本地菜单)。

任何建议或链接将不胜感激。谢谢。


当前回答

一种程序化的方式是在组件本身中完成。我在这个问题上挣扎了三周,但最终放弃了angular文档,转而阅读了让routerlinkactive工作的实际代码,这是我能找到的最好的文档了。

    import {
  Component,AfterContentInit,OnDestroy, ViewChild,OnInit, ViewChildren, AfterViewInit, ElementRef, Renderer2, QueryList,NgZone,ApplicationRef
}
  from '@angular/core';
  import { Location } from '@angular/common';

import { Subscription } from 'rxjs';
import {
  ActivatedRoute,ResolveStart,Event, Router,RouterEvent, NavigationEnd, UrlSegment
} from '@angular/router';
import { Observable } from "rxjs";
import * as $ from 'jquery';
import { pairwise, map } from 'rxjs/operators';
import { filter } from 'rxjs/operators';
import {PageHandleService} from '../pageHandling.service'
@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.scss']
})




export class HeaderComponent implements AfterContentInit,AfterViewInit,OnInit,OnDestroy{

    public previousUrl: any;
    private subscription: Subscription;


      @ViewChild("superclass", { static: false } as any) superclass: ElementRef;
      @ViewChildren("megaclass") megaclass: QueryList<ElementRef>;


  constructor( private element: ElementRef, private renderer: Renderer2, private router: Router, private activatedRoute: ActivatedRoute, private location: Location, private pageHandleService: PageHandleService){
    this.subscription = router.events.subscribe((s: Event) => {
      if (s instanceof NavigationEnd) {
        this.update();
      }
    });


  }


  ngOnInit(){

  }


  ngAfterViewInit() {
  }

  ngAfterContentInit(){
  }



private update(): void {
  if (!this.router.navigated || !this.superclass) return;
      Promise.resolve().then(() => {
        this.previousUrl = this.router.url

        this.megaclass.toArray().forEach( (superclass) => {

          var superclass = superclass
          console.log( superclass.nativeElement.children[0].classList )
          console.log( superclass.nativeElement.children )

          if (this.previousUrl == superclass.nativeElement.getAttribute("routerLink")) {
            this.renderer.addClass(superclass.nativeElement.children[0], "box")
            console.log("add class")

          } else {
            this.renderer.removeClass(superclass.nativeElement.children[0], "box")
            console.log("remove class")
          }

        });
})
//update is done
}
ngOnDestroy(): void { this.subscription.unsubscribe(); }


//class is done
}

注意: 对于编程方式,请确保添加router-link,并且它接受一个子元素。如果你想要改变它,你需要在superclass.nativeElement上去掉子元素。

其他回答

在简单的情况下,当有一个链接并且你想应用一些类时,使用routerLinkActive是很好的。但在更复杂的情况下,你可能没有routerLink,或者你需要更多的东西,你可以创建并使用管道:

@Pipe({
    name: "isRouteActive",
    pure: false
})
export class IsRouteActivePipe implements PipeTransform {

    constructor(private router: Router,
                private activatedRoute: ActivatedRoute) {
    }

    transform(route: any[], options?: { queryParams?: any[], fragment?: any, exact?: boolean }) {
        if (!options) options = {};
        if (options.exact === undefined) options.exact = true;

        const currentUrlTree = this.router.parseUrl(this.router.url);
        const urlTree = this.router.createUrlTree(route, {
            relativeTo: this.activatedRoute,
            queryParams: options.queryParams,
            fragment: options.fragment
        });
        return containsTree(currentUrlTree, urlTree, options.exact);
    }
}

然后:

<div *ngIf="['/some-route'] | isRouteActive">...</div>

不要忘记在管道依赖项中包含管道;)

现在我正在使用rc。4与bootstrap 4和这个对我来说是完美的:

 <li class="nav-item" routerLinkActive="active" [routerLinkActiveOptions]="{exact:
true}">
    <a class="nav-link" [routerLink]="['']">Home</a>
</li>

这将适用于url: /home

一种程序化的方式是在组件本身中完成。我在这个问题上挣扎了三周,但最终放弃了angular文档,转而阅读了让routerlinkactive工作的实际代码,这是我能找到的最好的文档了。

    import {
  Component,AfterContentInit,OnDestroy, ViewChild,OnInit, ViewChildren, AfterViewInit, ElementRef, Renderer2, QueryList,NgZone,ApplicationRef
}
  from '@angular/core';
  import { Location } from '@angular/common';

import { Subscription } from 'rxjs';
import {
  ActivatedRoute,ResolveStart,Event, Router,RouterEvent, NavigationEnd, UrlSegment
} from '@angular/router';
import { Observable } from "rxjs";
import * as $ from 'jquery';
import { pairwise, map } from 'rxjs/operators';
import { filter } from 'rxjs/operators';
import {PageHandleService} from '../pageHandling.service'
@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.scss']
})




export class HeaderComponent implements AfterContentInit,AfterViewInit,OnInit,OnDestroy{

    public previousUrl: any;
    private subscription: Subscription;


      @ViewChild("superclass", { static: false } as any) superclass: ElementRef;
      @ViewChildren("megaclass") megaclass: QueryList<ElementRef>;


  constructor( private element: ElementRef, private renderer: Renderer2, private router: Router, private activatedRoute: ActivatedRoute, private location: Location, private pageHandleService: PageHandleService){
    this.subscription = router.events.subscribe((s: Event) => {
      if (s instanceof NavigationEnd) {
        this.update();
      }
    });


  }


  ngOnInit(){

  }


  ngAfterViewInit() {
  }

  ngAfterContentInit(){
  }



private update(): void {
  if (!this.router.navigated || !this.superclass) return;
      Promise.resolve().then(() => {
        this.previousUrl = this.router.url

        this.megaclass.toArray().forEach( (superclass) => {

          var superclass = superclass
          console.log( superclass.nativeElement.children[0].classList )
          console.log( superclass.nativeElement.children )

          if (this.previousUrl == superclass.nativeElement.getAttribute("routerLink")) {
            this.renderer.addClass(superclass.nativeElement.children[0], "box")
            console.log("add class")

          } else {
            this.renderer.removeClass(superclass.nativeElement.children[0], "box")
            console.log("remove class")
          }

        });
})
//update is done
}
ngOnDestroy(): void { this.subscription.unsubscribe(); }


//class is done
}

注意: 对于编程方式,请确保添加router-link,并且它接受一个子元素。如果你想要改变它,你需要在superclass.nativeElement上去掉子元素。

让我们说你想添加CSS到我的active state/标签。使用routerLinkActive激活路由链路。

注意:'active'是我的类名

<style>
   .active{
       color:blue;
     }
</style>

  <a routerLink="/home" [routerLinkActive]="['active']">Home</a>
  <a routerLink="/about" [routerLinkActive]="['active']">About</a>
  <a routerLink="/contact" [routerLinkActive]="['active']">Contact</a>

下面是使用RouteData根据当前路由样式化菜单栏项的方法:

routecconfig包含了tab(当前路由)的数据:

@RouteConfig([
  {
    path: '/home',    name: 'Home',    component: HomeComponent,
    data: {activeTab: 'home'},  useAsDefault: true
  }, {
    path: '/jobs',    name: 'Jobs',    data: {activeTab: 'jobs'},
    component: JobsComponent
  }
])

一份布局:

  <li role="presentation" [ngClass]="{active: isActive('home')}">
    <a [routerLink]="['Home']">Home</a>
  </li>
  <li role="presentation" [ngClass]="{active: isActive('jobs')}">
    <a [routerLink]="['Jobs']">Jobs</a>
  </li>

类:

export class MainMenuComponent {
  router: Router;

  constructor(data: Router) {
    this.router = data;
  }

  isActive(tab): boolean {
    if (this.router.currentInstruction && this.router.currentInstruction.component.routeData) {
      return tab == this.router.currentInstruction.component.routeData.data['activeTab'];
    }
    return false;
  }
}