Angular 2可选的路由参数

在Angular 2的路由中可以有一个可选的路由参数吗?我尝试了Angular 1。但是在routecconfig中收到如下错误:

“ORIGINAL EXCEPTION: Path /user/:id?”包含“?”,这在路由配置中是不允许的。

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

你可以定义多个带参数和不带参数的路由:

@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

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

路由参数还是查询参数?

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

时优先使用路由参数

  • 该值是必选项。
  • 用于区分不同的路由路径。

时首选查询参数

  • 可选参数。
  • 该值为复杂和/或多变量。

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

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

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

使用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参数知道下一个路由是什么。

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

这样做:

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},
...

遇到了这个问题的另一个例子,为了寻找解决方案,我来到了这里。我的问题是,我正在做的孩子,和惰性加载组件以及优化事情一点。简而言之,如果你懒于加载父模块。主要的事情是我在路线中使用'/:id',它抱怨'/'是它的一部分。这不是真正的问题,但它适用。

从父应用程序路由

...
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
},
]
}
];
...
{path: 'users', redirectTo: 'users/', pathMatch: 'full'},
{path: 'users/:userId', component: UserComponent}

这样,在添加参数时就不会重新呈现组件。

Rerezz的回答很不错,但它有一个严重的缺陷。它导致User组件重新运行ngOnInit方法。

当你在那里做一些繁重的工作时它可能会有问题当你从非参数路线切换到参数路线时,你不希望它重新运行。虽然这两个路由是为了模仿一个可选的url参数,而不是成为两个独立的路由。

下面是我解决这个问题的建议:

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

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

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

我不能评论,但参考:Angular 2可选的路由参数

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

这里建议的答案,包括来自rerezz接受的答案,它建议添加多个路由条目。

然而,当路由表项之间发生变化时,即在带参数的路由表项和不带参数的路由表项之间,组件将被重新创建。

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

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

然后在路由配置中使用matcher:

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

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

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中检查它并相应地执行操作;else, id是id,然后继续。

  • 组件作用于selectedUser的其余部分是否未定义(*ngIf之类的)。

使用这个匹配器函数,您可以在不重新渲染组件的情况下获得理想的行为。当url。长度等于0,没有可选参数,url。长度等于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,
}]

在Angular 8中,你可以在不改变路由器配置的情况下简单地添加参数。

< a href = " https://angular。io/guide/router-tutorial-toh# navigation -back- the-list-component" rel="nofollow noreferrer">Angular Doc可选参数

在yourModule.routing.module.ts

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

在模板中:

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

主细节视图也有同样的问题。主视图可以在没有: 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

通过路由将路由参数从一个组件发送到另一个组件有三种方式。但是首先要将这些库导入到与.ts文件相关的组件中,并在构造函数中进行定义

private route: ActivatedRoute
private router: Router

第一种方式:必需的路由参数

//Route Configuration
{path: 'user/:id', component: UserDetailComponent}


//Set Hyperlink/routerLink
<a [routerLink]="['/user', user.id]"></a>


//Requesting Url after click on hyperlink
http://localhost:4200/user/6


//Now you can read id value in navigated component
this.route.snapshot.paramMap.get('id');

第二种方式:可选路径参数

//Route Configuration
{path: 'user', component: UserDetailComponent}
    

//Set Hyperlink/routerLink
<a [routerLink]=['/user', {name: userName, status: true}]"></a>




//Requesting Url after click on hyperlink
http://localhost:4200/user;name:userNameValue;status:true


//Now you can read values in navigated component
this.route.snapshot.paramMap.get('userId');
this.route.snapshot.paramMap.get('userName');

第三种方式:可选路径参数

//Route Configuration
{path: 'user', component: UserDetailComponent}
    

//Set Hyperlink/routerLink
<a [routerLink]="['/user']"  [queryParms]="{userId:'911', status:true}"></a>


//Requesting Url after click on hyperlink
http://localhost:4200/user?userId=911&status=true


    

//Now you can read values in navigated component
this.route.snapshot.paramMap.get('userId');
this.route.snapshot.paramMap.get('userName');

参考:https://qastack.mx/programming/44864303/send-data-through-routing-paths-in-angular