Javascript Angular 2 可选路由参数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34208745/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 16:03:38  来源:igfitidea点击:

Angular 2 optional route parameter

javascriptangular

提问by Jeroen

Is it possible to have an optional route parameter in the Angular 2 route? I tried the Angular 1.x syntax in RouteConfig but received below error:

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

"ORIGINAL EXCEPTION: Path "/user/:id?" contains "?" which is not allowed in a route config."

“原始例外:路径“/user/:id?”包含“?”,这在路由配置中是不允许的。”

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

回答by rerezz

You can define multiple routes with and without parameter:

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

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

and handle the optional parameter in your component:

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

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

    if (paramId) {
        ...
    }
}

See also the related github issue: https://github.com/angular/angular/issues/3525

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

回答by Martin Cremer

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

This way the component isn't re-rendered when the parameter is added.

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

回答by Jp_

It's recommended to use a query parameter when the information is optional.

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

Route Parameters or Query Parameters?

There is no hard-and-fast rule. In general,

prefer a route parameter when

  • the value is required.
  • the value is necessary to distinguish one route path from another.

prefer a query parameter when

  • the value is optional.
  • the value is complex and/or multi-variate.

路由参数还是查询参数?

没有硬性规定。一般来说,

更喜欢路由参数时

  • 该值是必需的。
  • 该值对于区分一条路由路径和另一条路由路径是必要的。

更喜欢查询参数时

  • 该值是可选的。
  • 该值是复杂的和/或多变量的。

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

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

You just need to take out the parameter from the route path.

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

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

回答by ObjectiveTC

Angular 4 - Solution to address the ordering of the optional parameter:

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

DO THIS:

做这个:

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

Note that the productsand products/:idroutes are named exactly the same. Angular 4 will correctly follow productsfor routes with no parameter, and if a parameter it will follow products/:id.

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

However, the path for the non-parameter route productsmust nothave a trailing slash, otherwise angular will incorrectly treat it as a parameter-path. So in my case, I had the trailing slash for products and it wasn't working.

然而,对于非参数路由路径products必须不能有斜线,否则角度将错误地把它当作一个参数路径。所以就我而言,我有产品的尾随斜线,但它不起作用。

DON'T DO THIS:

不要这样做:

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

回答by matewka

rerezz's answer is pretty nice but it has one serious flaw. It causes Usercomponent to re-run the ngOnInitmethod.

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

It might be problematic when you do some heavy stuff there and don't want it to be re-run when you switch from the non-parametric route to the parametric one. Though those two routes are meant to imitate an optional url parameter, not become 2 separate routes.

当您在那里执行一些繁重的工作并且在从非参数路由切换到参数路由时不希望它重新运行时,这可能会出现问题。尽管这两条路由旨在模仿可选的 url 参数,但不会成为 2 条独立的路由。

Here's what I suggest to solve the problem:

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

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

Then you can move the logic responsible for handling the param to the UserWithParamcomponent and leave the baselogic in the Usercomponent. Whatever you do in User::ngOnInitwon't be run again when you navigate from /userto /user/123.

然后你可以将负责处理参数的逻辑移到UserWithParam组件中,并将基本逻辑留在User组件中。User::ngOnInit当您从/user导航到/user/123时,无论您做什么都不会再次运行。

Don't forget to put the <router-outlet></router-outlet>in the User's template.

不要忘了把<router-outlet></router-outlet>User的模板。

回答by Wayne Maurer

The suggested answers here, including the accepted answerfrom rerezzwhich suggest adding multiple route entries work fine.

这里的参考答案,包括接受的答案rerezz这表明添加多个路由条目做工精细。

However the component will be recreated when changing between the route entries, i.e. between the route entry with the parameter and the entry without the parameter.

然而,当在路由条目之间,即在带有参数的路由条目和没有参数的条目之间进行更改时,将重新创建组件。

If you want to avoid this, you can create your own route matcher which will match both routes:

如果你想避免这种情况,你可以创建自己的路由匹配器来匹配两条路由:

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);
 }

Then use the matcher in your route config:

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

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

回答by Ravi Jadhav

With angular4 we just need to organise routes together in hierarchy

使用 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 
  }
];

This works for me . This way router know what is the next route based on option id parameters.

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

回答by L.P.

Ran into another instance of this problem, and in searching for a solution to it came here. My issue was that I was doing the children, and lazy loading of the components as well to optimize things a bit. In short if you are lazy loading the parent module. Main thing was my using '/:id' in the route, and it's complaints about '/' being a part of it. Not the exact problem here, but it applies.

遇到此问题的另一个实例,并在寻找解决方案时来到这里。我的问题是我正在做孩子,以及组件的延迟加载以优化一些东西。简而言之,如果您懒惰加载父模块。主要是我在路由中使用了 '/:id',它抱怨 '/' 是它的一部分。不是这里的确切问题,但它适用。

App-routing from parent

来自父级的应用程序路由

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

Child routes lazy loaded

子路由懒加载

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

回答by Javier Sedano

Facing a similar problem with lazy loading I have done this:

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

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

And then in the component:

然后在组件中:

  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);
  }

This way:

这边走:

  • The route without /is redirected to the route with. Because of the pathMatch: 'full', only such specific full route is redirected.

  • Then, users/:idis received. If the actual route was users/, idis "", so check it in ngOnInitand act accordingly; else, idis the id and proceed.

  • The rest of the componect acts on selectedUseris or not undefined (*ngIf and the things like that).

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

  • 然后,users/:id收到。如果实际路线是users/id"",那么请检查它ngOnInit并采取相应的行动;否则,id是 id 并继续。

  • 组件的其余部分selectedUser是否未定义(*ngIf 和类似的东西)。

回答by mschreib28

I can't comment, but in reference to: Angular 2 optional route parameter

我无法评论,但参考:Angular 2 optional route parameter

an update for Angular 6:

Angular 6 的更新:

import {map} from "rxjs/operators"

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

  if (paramId) {
    ...
  }
}

See https://angular.io/api/router/ActivatedRoutefor additional information on Angular6 routing.

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