Angular 7中是否有一种方法可以为路由命名?

20

我想知道在Angular7中是否有一种方法可以为我的路由命名,这样我就可以只调用 [routerLink]="myRouteName" 而不是 [routerLink]="/my/route/path"

如果可以,我该如何实现?


3
使用常量值。 - Rohit.007
没有直接可用的方法来为路由分配名称。但是,您可以通过创建一个与您打算使用的名称相同的路由(/myRouteName),并将其重定向到深层路由(/my/route/path)来解决此问题。 - Aragorn
你如何决定路由名称?想要在创建路由配置时硬编码吗? - Ashish Ranjan
6个回答

18

考虑在创建路由配置时配置路由名称。

利用routes数据属性为路由添加名称。(每个路由中的一些额外数据不会影响性能)。

但首先,让我们创建一个类,其中包含静态属性来保存路由名称和其实际路径。

export class RouteNames {
  public static routeNamesObject = {}
}

现在,在定义路由的组件中,让我们像这样编写:

const routes: Routes = [
  {path: "hello/:id", component: HelloComponent, data: {routeName: "Hello1"}},
  {path: "hello", component: HelloComponent, data: { routeName: "Hello2" }}
]

在这个变量初始化之后,设置RouteNames类的静态属性

routes.forEach((eachRoute) => {
  RouteNames.routeNamesObject[eachRoute.data.routeName] = eachRoute.path;    // now all route paths are added to this prop
})
在您的组件中创建一个公共变量以访问静态类,例如在app.component.ts中创建(您无需注入)。
结果:

在您的组件中创建一个公共变量以访问静态类,例如在app.component.ts中创建(您无需注入)。

public routeNames = RouteNames;

那么 app.component.html 将会如下:

<button [routerLink]="routeNames.routeNamesObject['Hello2']">Click to Navigate to Hello</button>

2
我考虑过这种方法,但我只是想确保没有其他选项。我想我得坚持类似这样的东西。你的解决方案很不错,但我想知道它是否为这个问题带来了太多的复杂性。设置一个.ts文件并在路由模块和组件中使用一个常量,这样会不会更好? - RafaelTSCS
哦,是的...拥有一个包含路径名称常量的单独文件更酷!我认为这样更好!在配置路由和在组件中使用常量。 - Ashish Ranjan
1
一个不用输入 "routeNames.routeNamesObject['...']" 的干净替代方法是定义一个管道(比如说 url),它可以这样做:routerLink="{{ 'Hello2' | url }}"。这样你就避免了在每个需要它们的组件中本地定义路由名称的问题。 - Safron
此外,你可以考虑创建一个 interface NamedRoute implements Route { name: string}type NamedRoutes = NamedRoute[],而不是将名称添加到数据属性中,然后使用这些接口。那么路由就会简单地看起来像 {path: "hello", component: HelloComponent, name: "Hello2" } - Safron
创建一个 NamedRouterModule,在 forRoot/forChild 方法中注册名称,也可以摆脱使用 routes.forEach(...) 自己注册名称的开销。也许我应该创建一个包... - Safron

7

我是这样做到的(如果有人能告诉我如何删除Array循环,那就更好了):

custom-route.interface.ts -- 用于为我们的路由对象添加名称


export interface ICustomRoute extends Route {

  name?: string;

}

在 routing.module.ts 中(或者你存储路由的任何其他位置),

const routes: ICustomRoute[] = [
  { path: 'some/random/page1', component: TestComponent, name: 'page1'  },
  { path: 'some/random/page2', component: Test2Component, name: 'page2'  },
  { path: 'page3', component: Test3Component, name: 'page3'  },
];

现在名称已经传递到您的路由模块中,因此现在您必须捕获名称并处理它。您可以通过多种方式完成此操作,我最终使用了一个指令(我看到@Safron也提到了管道)

named-routerlink.directive.ts

@Directive({
  selector: 'a[namedRouterLink]'
})
export class NamedRouterLinkDirective extends RouterLinkWithHref{
  @Input('namedRouterLink')

  set namedRouterLink(val: any) {
    const selectedRoute = this.myRoute.config.filter( x => x['name'] == val)[0];
    this.routerLink = "/" + selectedRoute['path']
  };

  constructor(router: Router, route: ActivatedRoute, locationStrategy: LocationStrategy, private myRoute: Router){
    super(router, route, locationStrategy)
  }

}

然后显然像这样使用:

 <a namedRouterLink="page1">Page 1</a>

管道版本:

@Pipe({name: 'getRoute' })
export class RoutePipe implements PipeTransform {

  constructor(private router: Router){}

  transform(routeName: string): string {
    const selectedRoute = this.router.config.filter( x => x['name'] == routeName)[0];
    return "/" + selectedRoute['path']
  }

}

管道示例:
 <a namedRouterLink="{{ 'page1' | getRoute }}">Page 1</a>

2
好的,我喜欢指令解决方案甚至比管道更好 :) - Safron
晚了点,但我非常喜欢那些解决方案! - RafaelTSCS
虽然有点晚,但是可以通过使用Array.find()而不是Array.filter()来稍微提高速度。 我喜欢这种方法。 - Kyoss

7
<a [routerLink]="routerLinkVariable"></a>

因此,此变量(routerLinkVariable)可以在类内部定义,并且其值应该如下所示。
export class myComponent {

     public routerLinkVariable = "/my/route/path"; // the value of the variable is string!
}

4

您可以使用常量文件来实现此目的,以便在其他组件中也可以重复使用。

export const ROUTE_URL = {
    myRouteName: '/my/route/path',
};

你可以使用任意个数的常量。

然后,在视图中使用该常量的 .TS 并使用它。

视图:

<a [routerLink]="routerUrls.myRouteName"></a>

.TS:

public routerUrls= ROUTE_URL;

即使在您的路由文件中也是如此

 { path: 'xyz', loadChildren:  ROUTE_URL.myRouteName},

我们在应用程序中使用相同的设置来从后端API加载路由。我们可以直接在.TS文件中使用常量变量,然后在视图中使用该变量。我们使用常量文件以提高代码的可用性,否则该URL也可以直接放在该变量中。 - Rohit.007
1
我见过这种方法,但是我不太舒服使用它。所以我一直在寻找可能的“开箱即用”的解决方案。我想我只能坚持使用这个了。 - RafaelTSCS
像这样带有ID的路径的常量会是什么样子?/my/contract/<id>/details/foo - Datz

3

在你的类中

public routeName = '/customRoute/myExample'

那么在你的模板中

[routerLink]="routeName"

我认为这应该可以将那个值提取出来,我想这就是你所要求的。只有当customRoute实际上是你已创建的有效路由名称时,它才能起作用。


0
这个虽然有点老,但是很疯狂的是Angular到现在还不支持这个功能,当应用程序变得越来越大,URL中有很多斜杠时,很难记住它们。
我已经成功创建了一个管道,支持路由命名,并且支持路由参数和查询参数,以下是代码:
import { Pipe, PipeTransform } from '@angular/core';
import { Router, Route } from '@angular/router';
import {isUndefined} from "util";

@Pipe({
  name: 'path'
})
export class RoutingPipe implements PipeTransform {
  private _path: string = null;
  constructor(
    private _router: Router
  ){}

  transform(_route_name: any, params?: {}): any {
    this._path = null;
    this.findPath(this._router.config, _route_name);
    if(this._path == null) throw new Error('No path found for name "'+_route_name+'"!');
    if(params){
      for (let k in params) {
        if (params.hasOwnProperty(k)) {
           this._path = this._path.replace(`:${k}`, params[k]);
        }
      }
    }
    return this._path;
  }

  /**
   * navigate to component by route name
   *
   * @param name route name
   * @param params route params if exist
   */
  navigate(name: string, params?: {}){
    this._router.navigate([this.transform(name, params)]);
  }

  /**
   * Find route's full path by name
   *
   * @param config routes
   * @param name route name
   * @param parent
   */
  findPath(config: Route[], name: String, parent?: string) {
    parent = parent || '';

    for (let i = 0; i < config.length; i++) {
      const route: Route = config[i];
      const path = parent + '/' + route.path;
      if (route.children) {
        // this._path = null;
        const currentPath = route.path ? parent + '/' + route.path : parent;
        this.findPath(route.children, name, currentPath);
      }else{
        if(!isUndefined(route.data) && (<any>route.data).name == name){
          this._path = path;
        }
      }
    }
  }

}

在routing.ts文件中声明它:
{ path: 'users/:id/edit', component: UserComponent, data: { name: 'edit_user' }}

你可以在你的HTML文件中这样使用它:
<a [routerLink]="'edit_user'|path:35">Some link</a>

也可以在你的component.ts文件中作为一个服务使用(确保在构造函数中注入它)。
editUser(){
    let userID = // look for user id
    this._router.navigate('edit_user', {id: userID});
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接