Ionic路由基础 #
一、路由概述 #
1.1 Ionic路由系统 #
Ionic使用Angular Router作为路由系统:
text
路由系统
│
├── 路由配置
│ ├── 路由定义
│ ├── 路由参数
│ └── 子路由
│
├── 导航方法
│ ├── routerLink
│ ├── Router.navigate
│ └── NavController
│
├── 路由守卫
│ ├── CanActivate
│ ├── CanDeactivate
│ └── Resolve
│
└── 路由事件
├── NavigationStart
├── NavigationEnd
└── NavigationError
1.2 路由文件 #
typescript
// app-routing.module.ts
import { NgModule } from '@angular/core';
import { PreloadAllModules, RouterModule, Routes } from '@angular/router';
const routes: Routes = [
{
path: '',
redirectTo: 'home',
pathMatch: 'full'
},
{
path: 'home',
loadChildren: () => import('./home/home.module').then(m => m.HomePageModule)
},
{
path: 'detail/:id',
loadChildren: () => import('./detail/detail.module').then(m => m.DetailPageModule)
}
];
@NgModule({
imports: [
RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })
],
exports: [RouterModule]
})
export class AppRoutingModule {}
二、路由配置 #
2.1 基本路由 #
typescript
const routes: Routes = [
// 重定向
{
path: '',
redirectTo: 'home',
pathMatch: 'full'
},
// 基本路由
{
path: 'home',
component: HomePage
},
// 懒加载路由
{
path: 'about',
loadChildren: () => import('./about/about.module').then(m => m.AboutPageModule)
}
];
2.2 路由参数 #
typescript
const routes: Routes = [
// 必需参数
{
path: 'detail/:id',
component: DetailPage
},
// 多个参数
{
path: 'user/:userId/post/:postId',
component: PostPage
},
// 可选参数(通过queryParams)
{
path: 'search',
component: SearchPage
}
];
2.3 子路由 #
typescript
const routes: Routes = [
{
path: 'settings',
component: SettingsPage,
children: [
{
path: '',
redirectTo: 'profile',
pathMatch: 'full'
},
{
path: 'profile',
component: ProfileSettingsComponent
},
{
path: 'security',
component: SecuritySettingsComponent
},
{
path: 'notifications',
component: NotificationSettingsComponent
}
]
}
];
2.4 命名路由出口 #
typescript
const routes: Routes = [
{
path: 'home',
component: HomePage,
children: [
{
path: 'detail/:id',
component: DetailComponent,
outlet: 'sidebar'
}
]
}
];
html
<!-- 主路由出口 -->
<ion-router-outlet></ion-router-outlet>
<!-- 命名路由出口 -->
<ion-router-outlet name="sidebar"></ion-router-outlet>
三、页面导航 #
3.1 routerLink导航 #
html
<!-- 基本导航 -->
<ion-button routerLink="/home">首页</ion-button>
<!-- 带参数导航 -->
<ion-button [routerLink]="['/detail', item.id]">详情</ion-button>
<!-- 带查询参数 -->
<ion-button
[routerLink]="['/search']"
[queryParams]="{ keyword: 'ionic', page: 1 }">
搜索
</ion-button>
<!-- 导航并替换历史 -->
<ion-button
routerLink="/login"
routerLinkActive="active"
[replaceUrl]="true">
登录
</ion-button>
3.2 Router.navigate #
typescript
import { Component } from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'app-home',
templateUrl: 'home.page.html'
})
export class HomePage {
constructor(private router: Router) {}
// 基本导航
goToAbout() {
this.router.navigate(['/about']);
}
// 带参数导航
goToDetail(id: number) {
this.router.navigate(['/detail', id]);
}
// 带查询参数
goToSearch() {
this.router.navigate(['/search'], {
queryParams: { keyword: 'ionic', page: 1 }
});
}
// 导航并替换历史
goToLogin() {
this.router.navigate(['/login'], {
replaceUrl: true
});
}
// 相对导航
goToChild() {
this.router.navigate(['./child'], { relativeTo: this.route });
}
goToParent() {
this.router.navigate(['../'], { relativeTo: this.route });
}
}
3.3 NavController导航 #
typescript
import { Component } from '@angular/core';
import { NavController } from '@ionic/angular';
@Component({
selector: 'app-home',
templateUrl: 'home.page.html'
})
export class HomePage {
constructor(private navCtrl: NavController) {}
// 前进导航(带动画)
goForward() {
this.navCtrl.navigateForward('/detail/1');
}
// 后退导航(带动画)
goBack() {
this.navCtrl.navigateBack('/home');
}
// 设置根页面
setRoot() {
this.navCtrl.navigateRoot('/login');
}
// 返回上一页
goBackOne() {
this.navCtrl.back();
}
// 返回到特定页面
goBackTo() {
this.navCtrl.pop();
}
}
四、路由参数获取 #
4.1 获取路径参数 #
typescript
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-detail',
templateUrl: 'detail.page.html'
})
export class DetailPage implements OnInit {
id: string = '';
constructor(private route: ActivatedRoute) {}
ngOnInit() {
// 方式1:快照获取
this.id = this.route.snapshot.paramMap.get('id') || '';
// 方式2:订阅获取(参数变化时更新)
this.route.paramMap.subscribe(params => {
this.id = params.get('id') || '';
});
}
}
4.2 获取查询参数 #
typescript
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-search',
templateUrl: 'search.page.html'
})
export class SearchPage implements OnInit {
keyword: string = '';
page: number = 1;
constructor(private route: ActivatedRoute) {}
ngOnInit() {
// 方式1:快照获取
this.keyword = this.route.snapshot.queryParamMap.get('keyword') || '';
this.page = Number(this.route.snapshot.queryParamMap.get('page')) || 1;
// 方式2:订阅获取
this.route.queryParamMap.subscribe(params => {
this.keyword = params.get('keyword') || '';
this.page = Number(params.get('page')) || 1;
});
}
}
4.3 获取路由数据 #
typescript
// 路由配置
const routes: Routes = [
{
path: 'detail/:id',
component: DetailPage,
data: {
title: '详情页',
showBackButton: true
}
}
];
// 组件获取
@Component({
selector: 'app-detail',
templateUrl: 'detail.page.html'
})
export class DetailPage implements OnInit {
title: string = '';
constructor(private route: ActivatedRoute) {}
ngOnInit() {
// 获取路由数据
this.title = this.route.snapshot.data['title'];
// 或订阅
this.route.data.subscribe(data => {
this.title = data['title'];
});
}
}
五、路由守卫 #
5.1 CanActivate守卫 #
typescript
// auth.guard.ts
import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
import { AuthService } from './auth.service';
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
constructor(
private auth: AuthService,
private router: Router
) {}
canActivate(): boolean {
if (this.auth.isLoggedIn()) {
return true;
}
this.router.navigate(['/login']);
return false;
}
}
// 路由配置
const routes: Routes = [
{
path: 'profile',
loadChildren: () => import('./profile/profile.module').then(m => m.ProfilePageModule),
canActivate: [AuthGuard]
}
];
5.2 CanDeactivate守卫 #
typescript
// unsaved-changes.guard.ts
import { Injectable } from '@angular/core';
import { CanDeactivate } from '@angular/router';
import { AlertController } from '@ionic/angular';
export interface CanComponentDeactivate {
canDeactivate: () => boolean;
}
@Injectable({
providedIn: 'root'
})
export class UnsavedChangesGuard implements CanDeactivate<CanComponentDeactivate> {
constructor(private alertCtrl: AlertController) {}
async canDeactivate(component: CanComponentDeactivate): Promise<boolean> {
if (component.canDeactivate && component.canDeactivate()) {
return true;
}
const alert = await this.alertCtrl.create({
header: '确认离开',
message: '您有未保存的更改,确定要离开吗?',
buttons: [
{
text: '取消',
role: 'cancel'
},
{
text: '确定',
handler: () => {
return true;
}
}
]
});
await alert.present();
return false;
}
}
// 组件实现
@Component({
selector: 'app-edit',
templateUrl: 'edit.page.html'
})
export class EditPage implements CanComponentDeactivate {
hasUnsavedChanges = false;
canDeactivate(): boolean {
return !this.hasUnsavedChanges;
}
}
5.3 Resolve守卫 #
typescript
// user.resolve.ts
import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot } from '@angular/router';
import { Observable } from 'rxjs';
import { UserService } from './user.service';
@Injectable({
providedIn: 'root'
})
export class UserResolve implements Resolve<any> {
constructor(private userService: UserService) {}
resolve(route: ActivatedRouteSnapshot): Observable<any> {
const id = route.paramMap.get('id');
return this.userService.getUser(id);
}
}
// 路由配置
const routes: Routes = [
{
path: 'user/:id',
component: UserPage,
resolve: {
user: UserResolve
}
}
];
// 组件获取
@Component({
selector: 'app-user',
templateUrl: 'user.page.html'
})
export class UserPage implements OnInit {
user: any;
constructor(private route: ActivatedRoute) {}
ngOnInit() {
this.user = this.route.snapshot.data['user'];
}
}
六、路由事件 #
6.1 监听路由事件 #
typescript
import { Component } from '@angular/core';
import { Router, NavigationStart, NavigationEnd, NavigationError } from '@angular/router';
@Component({
selector: 'app-root',
templateUrl: 'app.component.html'
})
export class AppComponent {
constructor(private router: Router) {
this.router.events.subscribe(event => {
if (event instanceof NavigationStart) {
console.log('导航开始:', event.url);
}
if (event instanceof NavigationEnd) {
console.log('导航结束:', event.url);
}
if (event instanceof NavigationError) {
console.log('导航错误:', event.error);
}
});
}
}
6.2 路由事件类型 #
| 事件 | 说明 |
|---|---|
| NavigationStart | 导航开始 |
| NavigationEnd | 导航结束 |
| NavigationCancel | 导航取消 |
| NavigationError | 导航错误 |
| RoutesRecognized | 路由识别 |
| GuardsCheckStart | 守卫检查开始 |
| GuardsCheckEnd | 守卫检查结束 |
| ResolveStart | Resolve开始 |
| ResolveEnd | Resolve结束 |
七、路由模块 #
7.1 模块路由配置 #
typescript
// home/home.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import { HomePage } from './home.page';
import { HomeRoutingModule } from './home-routing.module';
@NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
HomeRoutingModule
],
declarations: [HomePage]
})
export class HomePageModule {}
// home/home-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HomePage } from './home.page';
const routes: Routes = [
{
path: '',
component: HomePage
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class HomeRoutingModule {}
7.2 Tabs路由配置 #
typescript
// tabs/tabs.router.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { TabsPage } from './tabs.page';
const routes: Routes = [
{
path: '',
component: TabsPage,
children: [
{
path: 'home',
loadChildren: () => import('../home/home.module').then(m => m.HomePageModule)
},
{
path: 'search',
loadChildren: () => import('../search/search.module').then(m => m.SearchPageModule)
},
{
path: 'profile',
loadChildren: () => import('../profile/profile.module').then(m => m.ProfilePageModule)
},
{
path: '',
redirectTo: '/tabs/home',
pathMatch: 'full'
}
]
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class TabsPageRoutingModule {}
八、最佳实践 #
8.1 路由命名规范 #
typescript
// 推荐:小写+连字符
const routes: Routes = [
{ path: 'user-profile', component: UserProfilePage },
{ path: 'order-detail', component: OrderDetailPage }
];
// 不推荐:驼峰命名
const routes: Routes = [
{ path: 'userProfile', component: UserProfilePage }
];
8.2 懒加载 #
typescript
// 推荐:懒加载
const routes: Routes = [
{
path: 'detail',
loadChildren: () => import('./detail/detail.module').then(m => m.DetailPageModule)
}
];
// 不推荐:直接加载
const routes: Routes = [
{
path: 'detail',
component: DetailPage
}
];
8.3 路由数据 #
typescript
// 使用路由数据传递配置
const routes: Routes = [
{
path: 'detail/:id',
component: DetailPage,
data: {
title: '详情页',
showBackButton: true,
animation: 'slide-up'
}
}
];
九、总结 #
9.1 路由要点 #
| 要点 | 说明 |
|---|---|
| 路由配置 | 定义路由映射关系 |
| 页面导航 | routerLink、Router、NavController |
| 路由参数 | 路径参数、查询参数 |
| 路由守卫 | CanActivate、CanDeactivate、Resolve |
| 路由事件 | 监听导航过程 |
9.2 下一步 #
掌握了路由基础后,接下来让我们学习 页面导航,深入了解Ionic的导航机制!
最后更新:2026-03-28