在html中使用相对路径来指定相对路由。
/
开头的形式,路由器会从应用的 根路由 开始查找。
./
或 无前导斜线
形式是相对于 当前级别 的。
../
会回到当前路由路径的 上一级 。(比如:可以使用…/回到上一级,然后再进入兄弟路由路径中。)
<a routerLink="../second-component">Relative Route to second componenta>
在 ts 中
在ts中用 Router.navigate
方法配合 NavigationExtras
中的 relativeTo
属性来指定相对路由。我们必须提供当前的 ActivatedRoute
,来让路由器知道我们现在位于路由树中的什么位置。
constructor(
private router: Router,
private route: ActivatedRoute
) {}
goToItems() {
// navigate方法的参数2是NavigationExtras对象。把该对象的relativeTo属性设置为当前的ActivatedRoute,也就是this.route 。
this.router.navigate(['items'], { relativeTo: this.route });
}
3. RouterLink
路由参数
RouterModule中带参数的路由定义:
{ path: 'hero/:id', component: HeroDetailComponent }
在视图中设置路由参数:
<a [routerLink]="['/hero', hero.id]">
<router-outlet>router-outlet>
链接参数数组
3种形式:
<a [routerLink]="['/heroes']">Heroesa>
<a [routerLink]="['/hero', hero.id]">a>
<a [routerLink]="['/crisis-center', { foo: 'foo' }]">Crisis Centera>
几种写法的示例
示例A:相对于当前路径级别进行导航。
<a [routerLink]="['overview']">概览a>
<a [routerLink]="['logs']">日志a>
<a [routerLink]="['./overview']">概览a>
<a [routerLink]="['./logs']">日志a>
以上不等同于以下:
<a [routerLink]="['/overview']">概览a>
<a [routerLink]="['/logs']">日志a>
示例B:相对于上一级路径进行导航,使用 ../
。
<a [routerLink]="['../settings/basic']">基本设置a>
<a [routerLink]="['../settings/', 'basic']">基本设置a>
<a [routerLink]="['../settings', 'basic']">基本设置a>
const viewId = 'basic'
<a [routerLink]="['../settings', basic]">基本设置a>
示例C:设置路由参数。
<ng-container *ngFor="let view of views">
<a href="javascript:;" [routerLink]="['../', view._id]">{{ view.name }}a>
ng-container>
// ts
views = [
{ _id: 'all', name: '全部视图' },
{ _id: 'viewA', name: '视图A' },
{ _id: 'viewB', name: '视图B' },
{ _id: 'viewC', name: '视图C' }
];
示例D:使用矩阵URL标记法,在对象中传可选参数。
<a [routerLink]="['../settings/basic', { user: 'wumeimin', age: 18 }]">基本设置a>
示例E:指定路由的查询参数。
<a [routerLink]="['../settings/basic']" [queryParams]="{ user: 'wumeimin', age: 18 }">基本设置a>
4. Router
什么时候用 navigateByUrl?
当调用路由器的 Router.navigateByUrl()
时,url必须要指定完整的绝对路径。
navigateByUrl(url: string | UrlTree, extras: NavigationBehaviorOptions = {...})
什么时候使用?在不想基于当前路由树位置进行导航时使用。比如:
// 当前正处于页面 /xxx/xxxx/insights/default
// 要点击按钮跳转到绝对路径 /xxx/xxxx/itemDetail
this.router.navigateByUrl('/xxx/xxxx/itemDetail');
什么时候用 navigate?
基于所提供的 命令数组(参数1)
和 起点路由(在参数2的relativeTo指定)
进行 相对或绝对
导航。
navigate(commands: any[], extras: NavigationExtras = { skipLocationChange: false })
第二个参数NavigationExtras支持我们设置:
interface NavigationExtras extends UrlCreationOptions, NavigationBehaviorOptions {
// 允许从当前激活的路由进行相对导航。
// 如果传ActivatedRoute,则从当前激活路由进行相对导航。
// 如果没指定值,则从根路由进行绝对导航。
relativeTo?: ActivatedRoute | null ⭐️⭐️⭐️
// 设置URL的查询参数
queryParams?: Params | null ⭐️⭐️
// 设置url的哈希片段(#)
fragment?: string ⭐️⭐️
// 设置如何在路由器链接中处理查询参数以进行下一个导航。
// preserve:保留当前参数,将放弃所有新的查询参数。 比如:从 /view1?page=1 到 /view2?page=1
// merge:合并新的当前参数,将新的查询参数附加到当前URL的参数中。比如:从 /view1?page=1 到 /view2?page=1&otherKey=2
queryParamsHandling?: QueryParamsHandling | null ⭐️⭐️⭐️
// 在后续导航时保留 # 片段。 比如:从 /results#top 到 /view#top
preserveFragment?: boolean
// 值为true则导航时不把新状态记入历史
skipLocationChange?: boolean
// 值为true则导航时不把”当前状态“记入历史
replaceUrl?: boolean ⭐️⭐️⭐️
state?: {...}
}
示例A:使用navigate进行相对或绝对导航。
<!-- 场景:当前页面处于/xxx/xxxx/overview,当点击”日志“时,会导航到/xxx/xxxx/logs -->
<a [routerLink]="['overview']">概览</a>
<a [routerLink]="['logs']" (click)="toLogs()">日志</a>
// ts中以下几种写法均可达到目的
// 方式一:navigate相对导航 (relativeTo值为true时相对于当前激活路由进行导航)
this.router.navigate(['logs'], { relativeTo: this.route });
// 同:
this.router.navigate(['.', 'logs'], { relativeTo: this.route });
// 同:
this.router.navigate(['./', 'logs'], { relativeTo: this.route });
// 同:
this.router.navigate(['./logs'], { relativeTo: this.route });
// 方式二:navigate绝对导航 (relativeTo值为null时。命令数组需要能拼成一个完整的绝对路径)
this.router.navigate(['/xxx/xxxx/logs']);
// 方式三:navigateUrl绝对导航(需要提供绝对路径)
this.router.navigateByUrl('/xxx/xxxx/logs');
// 错误写法(该写法会从根路由/开始匹配,路由会瞬间跳到'/logs',由于没有匹配的,然后会被一路重定向到别的页面)
this.router.navigate(['logs']);
5. ActivatedRoute 查询路由数据
ActivatedRoute用于跟踪路由数据。
params 和 queryParams 的区别?
(1)params :表示当前路由范围内的矩阵参数 ;
,对应的映射是paramMap。
(2)queryParams :表示所有路由共享的查询参数 ?
,对应的映射是queryParamMap。
相同点:ActivatedRoute.params,ActivatedRoute.paramMap,ActivatedRoute.queryParams,ActivatedRoute.queryParamMap 都返回Observable。
什么时候用 params ?场景一:获取矩阵URL中的可选参数。
矩阵 URL标记法:在链接参数数组中,可以在对象中提供可选的路由参数。参数在URL中将以 ;
的形式出现。在导航到的组件中通过 params
或 paramMap
获取 可选参数 的数据。
<!-- 当前页面处于/xxx/xxxx/xxxxx/hahaha/viewId -->
<!-- 点击”基本设置“跳转到 /xxx/xxxx/xxxxx/hahaha/settings/basic;user=wumeimin;age=18 -->
<a [routerLink]="['../settings/basic', { user: 'wumeimin', age: 18 }]">基本设置</a>
// 也可以使用navigate
this.router.navigate(['../settings/basic', { user: 'wumeimin', age: 18 }], { relativeTo: this.route });
// 在导航到的组件中获取参数
import { ActivatedRoute, ParamMap } from '@angular/router';
// 方式一:使用paramMap获取(在参数发生变化时触发发射新值)
this.route.paramMap.subscribe((param: ParamMap) => {
console.log(param); // 返回的是一个ParamMap对象{params: {user: 'wumeimin', age: '18'}},它提供了get、getAll、has、keys等方法
param.get('user') // wumeimin
param.get('age') // 18
param.getAll('user') // ['wumeimin']
param.has('user') // true
param.keys // ['user', 'age']
});
// 方式二:使用params获取
this.route.params.subscribe((param: { user: string; age: number }) => {
console.log(param); // 返回的是 { user: 'wumeimin', age: 18 }
param.user // wumeimin
param.age // 18
});
// 注意:使用queryParams或queryParamMap获取不到上述数据。
场景二:跟踪一般场景下的路由参数变化。
RouterMoulde中的路由定义:
{
path: 'insight',
children: [
{
path: '',
pathMatch: 'full',
redirectTo: 'all'
},
{
path: ':viewId',
component: MyViewContainerComponent
}
]
}
视图中路由参数的设置:
// 场景:当前页面在 /xxx/xxxx/xxxxx/insight/all
// 点击”视图A“,会跳转到 /xxx/xxxx/xxxxx/insight/viewA
views = [
{ _id: 'all', name: '全部视图' },
{ _id: 'viewA', name: '视图A' },
{ _id: 'viewB', name: '视图B' },
{ _id: 'viewC', name: '视图C' }
];
<ng-container *ngFor="let view of views">
<a href="javascript:;" [routerLink]="['../', view._id]">{{ view.name }}</a>
</ng-container>
// 也可以使用 navigate
<ng-container *ngFor="let view of views">
<a href="javascript:;" (click)="toView(view._id)">{{ view.name }}</a>
</ng-container>
toView(viewId) {
this.router.navigate(['../', viewId], { relativeTo: this.route });
}
在导航到的组件中使用ActivatedRoute的params或paramMap获取路由参数viewId:
// 方式一:使用paramMap获取
this.route.paramMap.subscribe((param: ParamMap) => {
const viewId = param.get('viewId');
});
// 方式二:使用params获取
this.route.params.subscribe((param: { viewId: string }) => {
const viewId = param.viewId;
});
// 注意:使用queryParams或queryParamMap获取不到上述数据,因为这俩是用来订阅“查询参数”的。
什么时候用 queryParams ?
场景一: 用于获取查询参数。
在RouterLink中可以使用 queryParams
将查询参数添加到生成的URL。参数在URL中将以 ?
的形式出现,在导航到的组件中通过 queryParams 或 queryParamMap 获取 查询参数
的数据。
<!-- 场景:当前页面处于/xxx/xxxx/xxxxx/backlog/viewId -->
<!-- 点击”基本设置“跳转到 /xxx/xxxx/xxxxx/settings/basic?user=wumeimin&age=18 -->
<a [routerLink]="['../settings/basic']" [queryParams]="{ user: 'wumeimin', age: 18 }">基本设置</a>
// 也可以使用 navigate
this.router.navigate(['../settings/basic'], { relativeTo: this.route, queryParams: { user: 'wumeimin', age: 18 } });
// 在导航到的组件中获取参数
import { ActivatedRoute, ParamMap} from '@angular/router';
// 方式一:使用queryParamMap获取(在查询参数发生变化时才会触发发射新值)
this.route.queryParamMap.subscribe((queryParam: ParamMap) => {
console.log(queryParam); // 返回的是一个ParamMap对象,{params: {user: 'wumeimin', age: '18'}},它提供了get、getAll、has、keys等方法
queryParam.get('user') // wumeimin
queryParam.get('age') // 18
queryParam.getAll('user') // ['wumeimin']
queryParam.has('user') // true
queryParam.keys // ['user', 'age']
});
// 方式二:使用queryParams获取
this.route.queryParams.subscribe((queryParam: { user: string; age: number }) => {
console.log(queryParam); // 返回的是 { user: 'wumeimin', age: 18 }
console.log(queryParam.user); // wumeimin
console.log(queryParam.age); // 18
});
// 注意:使用params或paramMap获取不到上述数据,因为这俩是用来订阅“路由参数”的。
什么时候用 snapshot 快照?
当要导航到的组件不会被复用时,即当不需要检测路由变化时
我们可以直接使用 snapshot 快照来访问路由数据, snapshot 快照只能访问到初始值
。
const id = this.route.snapshot.paramMap.get('user');
const id = this.route.snapshot.param.user;
const id = this.route.snapshot.param['user'];
当要导航到的组件会随着路由参数的变化被复用时,我们不用 snapshot 快照,而是需要使用订阅者。由于 ngOnInit() 在每个组件实例化时只会被调用一次,所以需要使用 paramMap可观察对象
来检测路由参数在同一个实例中
何时发生了变化。
import { ActivatedRoute, ParamMap } from '@angular/router';
import { switchMap } from 'rxjs/operators';
constructor(
private route: ActivatedRoute,
private service: HeroService
) {}
ngOnInit() {
this.hero$ = this.route.paramMap.pipe(
switchMap((params: ParamMap) =>
// 检测到路由参数变化,拿取最新参数来进行下一步的数据更新 *** 作
this.service.getHero(params.get('id')!))
);
}
// 此示例中 switchMap *** 作符做了两件事。它把 HeroService 返回的 Observable 拍平,并取消以前的未完成请求。
// 当 HeroService 仍在检索旧的 id 时,如果用户使用新的 id 重新导航到这个路由,switchMap 会放弃那个旧请求,并返回新 id 的英雄。
一般在组件订阅可观察对象,通常需要在组件销毁时取消这个订阅。 但ActivatedRoute 中的可观察对象是一个例外,因为 ActivatedRoute 及其可观察对象与 Router 本身是隔离的。 Router 会在不再需要时销毁这个路由组件,这意味着此组件的所有成员也都会销毁,包括注入进来的 ActivatedRoute 以及那些对它的所有 Observable 属性的订阅。
6. replaceUrl:true的用法导航时使用 replaceUrl: true
,不把”当前状态“记入历史。当浏览器回退时,会跳过这个没被记录进历史的状态。示例验证:
<ng-container *ngFor="let view of views">
<a href="javascript:;" (click)="toView(view._id)">{{ view.name }}</a>
</ng-container>
views = [
{ _id: 'all', name: '全部视图' },
{ _id: 'viewA', name: '视图A' },
{ _id: 'viewB', name: '视图B' },
{ _id: 'viewC', name: '视图C' }
];
toView(viewId) {
if (viewId === 'viewA') {
// 在导航到viewA之前,不把“当前状态”记录进历史。(这里,从哪进入的viewA,哪就是当前状态)
this.router.navigate(['../', viewId], { relativeTo: this.route, replaceUrl: true });
} else {
this.router.navigate(['../', viewId], { relativeTo: this.route });
}
}
7.LocationStrategy 路由策略
两种路由策略:
// PathLocationStrategy策略:HTML 5 pushState 风格
localhost:3002/crisis-center/
// HashLocationStrategy策略:hash URL 风格
localhost:3002/src/#/crisis-center/
RouterModule.forRoot() 使用的是默认策略PathLocationStrategy。
几乎所有的 Angular 项目都会使用默认的 HTML 5 风格。它生成的 URL 更易于被用户理解,它也为将来做服务端渲染预留了空间。
现代 HTML 5 浏览器支持 history.pushState API, 这是一项可以改变浏览器的当前地址和历史,却又不会触发服务端页面请求的技术。
必须在应用的 index.html 中添加一个
元素才能让 pushState 路由正常工作。 浏览器要用
的值来为引用 CSS、脚本和图片文件时使用的相对 URL 添加前缀。
<base href="/">
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)