Angular 2可选路由参数

时间:2015-12-10 18:03:50

标签: javascript angular

Angular 2路线中是否有可选的路线参数?我在RouteConfig中尝试了Angular 1.x语法但收到了以下错误:

  

" ORIGINAL EXCEPTION:Path" / user /:id?"包含"?"在路由配置中不允许这样做。"

@RouteConfig([
{
    path: '/user/:id?',
    component: User,
    as: 'User'
}])

13 个答案:

答案 0 :(得分:216)

您可以使用和不使用参数定义多个路线:

@RouteConfig([
    { path: '/user/:id', component: User, name: 'User' },
    { path: '/user', component: User, name: 'Usernew' }
])

并处理组件中的可选参数:

constructor(params: RouteParams) {
    var paramId = params.get("id");

    if (paramId) {
        ...
    }
}

另请参阅相关的github问题:https://github.com/angular/angular/issues/3525

答案 1 :(得分:41)

{path: 'users', redirectTo: 'users/'},
{path: 'users/:userId', component: UserComponent}

这样,添加参数时不会重新渲染组件。

答案 2 :(得分:32)

当信息是可选的时,建议使用查询参数。

  

路由参数或查询参数?

     

没有严格的规则。一般来说,

     

时更喜欢路线参数      
      
  • 该值是必需的。
  •   
  • 该值必须区分一条路径与另一条路径。
  •   
     

时更喜欢查询参数      
      
  • 该值是可选的。
  •   
  • 值很复杂和/或多变量。
  •   

来自https://angular.io/guide/router#optional-route-parameters

您只需要从路径路径中取出参数。

@RouteConfig([
{
    path: '/user/',
    component: User,
    as: 'User'
}])

答案 3 :(得分:16)

Angular 4 - 解决可选参数排序的解决方案:

DO THIS:

const appRoutes: Routes = [
  {path: '', component: HomeComponent},
  {path: 'products', component: ProductsComponent},
  {path: 'products/:id', component: ProductsComponent}
]

请注意,productsproducts/:id路由的名称完全相同。对于没有参数的路线,Angular 4将正确地跟随products,如果参数将跟随products/:id

但是,非参数路由products的路径必须具有尾部斜杠,否则angular将错误地将其视为参数路径。所以在我的情况下,我有产品的尾部斜线,它没有工作。

不要这样做:

...
{path: 'products/', component: ProductsComponent},
{path: 'products/:id', component: ProductsComponent},
...

答案 4 :(得分:7)

rerezz的答案非常好,但它有一个严重的缺陷。它会导致User组件重新运行ngOnInit方法。

当你在那里做一些沉重的东西并且当你从非参数路线切换到参数路线时不希望它重新运行时,这可能会有问题。虽然这两条路线都是为了模仿一个可选的url参数,但不会成为两条不同的路径。

以下是我建议解决问题的方法:

const routes = [
  {
    path: '/user',
    component: User,
    children: [
      { path: ':id', component: UserWithParam, name: 'Usernew' }
    ]
  }
];

然后,您可以将负责处理param的逻辑移动到UserWithParam组件,并将 base 逻辑保留在User组件中。当您从 / user 导航到 / user / 123 时,无论您在User::ngOnInit中执行什么操作都不会再次运行。

不要忘记将<router-outlet></router-outlet>放在User的模板中。

答案 5 :(得分:3)

使用angular4,我们只需要在层次结构中组织路由

const appRoutes: Routes = [
  { path: '', component: MainPageComponent },
  { path: 'car/details', component: CarDetailsComponent },
  { 
    path: 'car/details/platforms-products', 
    component: CarProductsComponent 
  },
  { path: 'car/details/:id', component: CadDetailsComponent },
  { 
    path: 'car/details/:id/platforms-products', 
    component: CarProductsComponent 
  }
];

这对我有用。这样路由器就可以根据选项id参数知道下一条路由是什么。

答案 6 :(得分:1)

进入这个问题的另一个实例,并在搜索解决方案时来到这里。我的问题是我正在做孩子们,懒惰加载组件以及稍微优化一些事情。简而言之,如果您正在延迟加载父模块。主要是我使用&#39; /:id&#39;在路线上,它的抱怨是关于&#39; /&#39;成为它的一部分。这里不是确切的问题,但它适用。

来自父母的应用路由

...
const routes: Routes = [
  {
    path: '',
    children: [
      {
        path: 'pathOne',
        loadChildren: 'app/views/$MODULE_PATH.module#PathOneModule'
      },
      {
        path: 'pathTwo',
        loadChildren: 'app/views/$MODULE_PATH.module#PathTwoModule'
      },
...

子级路由延迟加载

...
const routes: Routes = [
  {
    path: '',
    children: [
      {
        path: '',
        component: OverviewComponent
      },
      {
        path: ':id',
        component: DetailedComponent
      },
    ]
  }
];
...

答案 7 :(得分:1)

在 Angular 8 中,您可以简单地添加参数而无需更改路由器配置。

Angular Doc Optional param

在 yourModule.routing.module.ts 中

const routes: Routes = [
  { path: 'somePath/:RequiredParam', component: Yourcomponent }
];

在您的模板中:

<div [RouterLink] = ['somePath', requiredParamValue, {optionalParam: value}]></div>

答案 8 :(得分:0)

我无法发表评论,但引用以下内容:Angular 2 optional route parameter

Angular 6的更新:

import {map} from "rxjs/operators"

constructor(route: ActivatedRoute) {
  let paramId = route.params.pipe(map(p => p.id));

  if (paramId) {
    ...
  }
}

有关Angular6路由的更多信息,请参见https://angular.io/api/router/ActivatedRoute

答案 9 :(得分:0)

此处建议的答案,包括来自accepted answerrerezz,建议添加多个路由条目可以正常工作。

但是,当在路由条目之间(即在带有参数的路由条目和不带参数的条目之间)进行更改时,将重新创建组件。

如果要避免这种情况,可以创建自己的路线匹配器,以匹配两条路线:

export function userPageMatcher(segments: UrlSegment[]): UrlMatchResult {
    if (segments.length > 0 && segments[0].path === 'user') {
        if (segments.length === 1) {
            return {
                consumed: segments,
                posParams: {},
            };
        }
        if (segments.length === 2) {
            return {
                consumed: segments,
                posParams: { id: segments[1] },
            };
        }
        return <UrlMatchResult>(null as any);
    }
    return <UrlMatchResult>(null as any);
 }

然后在路由配置中使用匹配器:

const routes: Routes = [
    {
        matcher: userPageMatcher,
        component: User,
    }
];

答案 10 :(得分:0)

面对类似的延迟加载问题,我已经这样做了:

const routes: Routes = [
  {
    path: 'users',
    redirectTo: 'users/',
    pathMatch: 'full'
  },
  {
    path: 'users',
    loadChildren: './users/users.module#UserssModule',
    runGuardsAndResolvers: 'always'
  },
[...]

然后在组件中:

  ngOnInit() {
    this.activatedRoute.paramMap.pipe(
      switchMap(
        (params: ParamMap) => {
          let id: string = params.get('id');
          if (id == "") {
            return of(undefined);
          }
          return this.usersService.getUser(Number(params.get('id')));
        }
      )
    ).subscribe(user => this.selectedUser = user);
  }

这种方式:

  • 没有/的路由被重定向到的路由。由于pathMatch: 'full',仅重定向了这种特定的完整路由。

  • 然后,收到users/:id。如果实际路线为users/,则id"",因此请在ngOnInit中进行检查并采取相应措施;否则,id是ID,然后继续。

  • selectedUser起作用的其余部分尚未定义(* ngIf和类似的东西)。

答案 11 :(得分:0)

使用此匹配器功能,无需重新渲染组件即可获得理想的行为。当url.length等于0时,没有可选参数,而url.length等于1,则有1个可选参数。 id-是可选参数的名称。

  const routes: Routes = [
  {
    matcher: (segments) => {
      if (segments.length <= 1) {
        return {
          consumed: segments,
          posParams: {
            id: new UrlSegment(segments[0]?.path || '', {}),
          },
        };
      }
      return null;
    },
    pathMatch: 'prefix',
    component: UserComponent,
  }]

答案 12 :(得分:0)

主从视图也有同样的问题。主视图可以在没有 :elementId 参数的情况下可见,但仍应在打开详细信息选择并在 url 中使用 :elementId 显示。

我是这样解决的:

const routes: Routes = [
  {
    path: '',
    component: MasterDetailComponent,
    children: [
      {
        path: ':elementId',
        children: [
          {
            path: 'details',
            component: DetailComponent
          },
          {
            path: '',
            redirectTo: 'details'
          }
        ]
      }
    ]
  }
];

然后在 MasterDetailComponent(例如在 ngOnInit 方法中)您可以使用子路由获取 :elementId

const childRouteWithElementId = this.route.snapshot.children[0];
const elementIdFromUrl = childRouteWithElementId.params.elementId;
if (!!elementIdFromUrl ) {
  // Do what you need to with the optional parameter
}

当然,你可以在没有子路由的情况下做同样的事情,并且在 url 末尾只有可选的 elementId