Ionic页面导航 #
一、导航概述 #
1.1 Ionic导航系统 #
Ionic提供两种导航方式:
text
导航系统
│
├── URL路由(推荐)
│ ├── Angular Router
│ ├── URL驱动
│ └── 支持浏览器历史
│
└── NavController
├── 栈式导航
├── push/pop操作
└── 动画支持
1.2 导航栈 #
text
导航栈示例:
[Login] → [Home] → [Detail] → [Settings]
当前页面: Settings
返回顺序: Settings → Detail → Home → Login
二、页面跳转 #
2.1 声明式导航 #
html
<!-- 使用routerLink -->
<ion-button routerLink="/home">首页</ion-button>
<!-- 带参数 -->
<ion-button [routerLink]="['/detail', item.id]">详情</ion-button>
<!-- 带查询参数 -->
<ion-button
[routerLink]="['/search']"
[queryParams]="{ q: 'ionic' }">
搜索
</ion-button>
<!-- 列表项导航 -->
<ion-item [routerLink]="['/detail', item.id]">
<ion-label>{{ item.name }}</ion-label>
</ion-item>
<!-- 卡片导航 -->
<ion-card [routerLink]="['/product', product.id]">
<ion-card-header>
<ion-card-title>{{ product.name }}</ion-card-title>
</ion-card-header>
</ion-card>
2.2 编程式导航 #
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) {}
// 基本跳转
navigateToAbout() {
this.router.navigate(['/about']);
}
// 带路径参数
navigateToDetail(id: string) {
this.router.navigate(['/detail', id]);
}
// 带查询参数
navigateToSearch() {
this.router.navigate(['/search'], {
queryParams: {
keyword: 'ionic',
page: 1
}
});
}
// 带路由数据
navigateWithData() {
this.router.navigate(['/detail', 1], {
state: {
data: { name: 'Ionic' }
}
});
}
// 替换当前历史
navigateAndReplace() {
this.router.navigate(['/home'], {
replaceUrl: true
});
}
}
2.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();
}
// 返回到特定页面
goBackToRoot() {
this.navCtrl.goBack('/home');
}
}
三、参数传递 #
3.1 路径参数 #
typescript
// 发送页面
goToDetail(id: string) {
this.router.navigate(['/detail', id]);
}
// 接收页面
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() {
// 快照获取
this.id = this.route.snapshot.paramMap.get('id') || '';
// 订阅获取
this.route.paramMap.subscribe(params => {
this.id = params.get('id') || '';
this.loadDetail(this.id);
});
}
loadDetail(id: string) {
// 加载详情数据
}
}
3.2 查询参数 #
typescript
// 发送页面
goToSearch() {
this.router.navigate(['/search'], {
queryParams: {
keyword: 'ionic',
category: 'mobile',
page: 1
}
});
}
// 接收页面
@Component({
selector: 'app-search',
templateUrl: 'search.page.html'
})
export class SearchPage implements OnInit {
keyword: string = '';
category: string = '';
page: number = 1;
constructor(private route: ActivatedRoute) {}
ngOnInit() {
// 快照获取
this.keyword = this.route.snapshot.queryParamMap.get('keyword') || '';
this.category = this.route.snapshot.queryParamMap.get('category') || '';
this.page = Number(this.route.snapshot.queryParamMap.get('page')) || 1;
// 订阅获取
this.route.queryParamMap.subscribe(params => {
this.keyword = params.get('keyword') || '';
this.category = params.get('category') || '';
this.page = Number(params.get('page')) || 1;
this.search();
});
}
search() {
// 执行搜索
}
}
3.3 路由状态 #
typescript
// 发送页面
import { Router } from '@angular/router';
goToDetail(product: any) {
this.router.navigate(['/detail', product.id], {
state: {
product: product
}
});
}
// 接收页面
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'app-detail',
templateUrl: 'detail.page.html'
})
export class DetailPage implements OnInit {
product: any;
constructor(private router: Router) {}
ngOnInit() {
const navigation = this.router.getCurrentNavigation();
const state = navigation?.extras.state;
this.product = state?.['product'];
}
}
3.4 服务共享数据 #
typescript
// data.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class DataService {
private productSource = new BehaviorSubject<any>(null);
currentProduct = this.productSource.asObservable();
setProduct(product: any) {
this.productSource.next(product);
}
getProduct() {
return this.productSource.value;
}
clearProduct() {
this.productSource.next(null);
}
}
// 发送页面
import { DataService } from './data.service';
export class ListPage {
constructor(
private router: Router,
private dataService: DataService
) {}
goToDetail(product: any) {
this.dataService.setProduct(product);
this.router.navigate(['/detail', product.id]);
}
}
// 接收页面
export class DetailPage implements OnInit {
product: any;
constructor(
private route: ActivatedRoute,
private dataService: DataService
) {}
ngOnInit() {
// 从服务获取
this.product = this.dataService.getProduct();
// 或订阅
this.dataService.currentProduct.subscribe(product => {
this.product = product;
});
}
}
四、返回处理 #
4.1 返回按钮 #
html
<!-- 基本返回按钮 -->
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button defaultHref="/home"></ion-back-button>
</ion-buttons>
<ion-title>详情页</ion-title>
</ion-toolbar>
</ion-header>
<!-- 自定义返回按钮 -->
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-button (click)="goBack()">
<ion-icon name="arrow-back" slot="icon-only"></ion-icon>
</ion-button>
</ion-buttons>
<ion-title>详情页</ion-title>
</ion-toolbar>
</ion-header>
typescript
import { Component } from '@angular/core';
import { NavController } from '@ionic/angular';
@Component({
selector: 'app-detail',
templateUrl: 'detail.page.html'
})
export class DetailPage {
constructor(private navCtrl: NavController) {}
goBack() {
this.navCtrl.back();
}
}
4.2 返回数据 #
typescript
// 详情页返回数据
import { Component } from '@angular/core';
import { NavController } from '@ionic/angular';
@Component({
selector: 'app-detail',
templateUrl: 'detail.page.html'
})
export class DetailPage {
constructor(private navCtrl: NavController) {}
saveAndReturn() {
// 保存数据
this.saveData();
// 返回并传递数据
this.navCtrl.navigateBack('/home', {
state: {
saved: true,
data: this.formData
}
});
}
}
// 首页接收返回数据
import { Component } from '@angular/core';
import { Router } from '@ionic/angular';
@Component({
selector: 'app-home',
templateUrl: 'home.page.html'
})
export class HomePage {
constructor(private router: Router) {
this.router.events.subscribe(event => {
if (event instanceof NavigationEnd) {
const navigation = this.router.getCurrentNavigation();
const state = navigation?.extras.state;
if (state?.['saved']) {
// 处理返回数据
this.refreshData();
}
}
});
}
}
4.3 确认返回 #
typescript
import { Component } from '@angular/core';
import { AlertController } from '@ionic/angular';
@Component({
selector: 'app-edit',
templateUrl: 'edit.page.html'
})
export class EditPage {
hasChanges = false;
constructor(
private alertCtrl: AlertController,
private navCtrl: NavController
) {}
async confirmBack() {
if (!this.hasChanges) {
this.navCtrl.back();
return;
}
const alert = await this.alertCtrl.create({
header: '确认离开',
message: '您有未保存的更改,确定要离开吗?',
buttons: [
{
text: '取消',
role: 'cancel'
},
{
text: '放弃更改',
handler: () => {
this.navCtrl.back();
}
},
{
text: '保存并离开',
handler: () => {
this.saveData();
this.navCtrl.back();
}
}
]
});
await alert.present();
}
}
五、导航生命周期 #
5.1 Ionic生命周期 #
typescript
import { Component } from '@angular/core';
@Component({
selector: 'app-detail',
templateUrl: 'detail.page.html'
})
export class DetailPage {
// 页面即将进入
ionViewWillEnter() {
console.log('页面即将进入');
// 刷新数据
this.refreshData();
}
// 页面已进入
ionViewDidEnter() {
console.log('页面已进入');
// 页面动画完成
}
// 页面即将离开
ionViewWillLeave() {
console.log('页面即将离开');
// 保存临时数据
}
// 页面已离开
ionViewDidLeave() {
console.log('页面已离开');
// 清理资源
}
}
5.2 生命周期流程 #
text
首次进入页面:
ngOnInit → ionViewWillEnter → ionViewDidEnter
离开页面:
ionViewWillLeave → ionViewDidLeave
返回页面:
ionViewWillEnter → ionViewDidEnter
销毁页面:
ionViewWillLeave → ionViewDidLeave → ngOnDestroy
5.3 生命周期使用场景 #
| 生命周期 | 使用场景 |
|---|---|
| ionViewWillEnter | 刷新数据、重置状态 |
| ionViewDidEnter | 启动动画、开始定时器 |
| ionViewWillLeave | 保存数据、暂停操作 |
| ionViewDidLeave | 清理资源、停止定时器 |
六、导航动画 #
6.1 页面过渡动画 #
typescript
import { AnimationController } from '@ionic/angular';
// 自定义进入动画
const enterAnimation = (baseEl: HTMLElement) => {
const animationCtrl = new AnimationController();
return animationCtrl
.create()
.addElement(baseEl)
.duration(300)
.fromTo('opacity', '0', '1')
.fromTo('transform', 'translateX(100%)', 'translateX(0)');
};
// 自定义离开动画
const leaveAnimation = (baseEl: HTMLElement) => {
return enterAnimation(baseEl).direction('reverse');
};
6.2 导航方向 #
typescript
// 前进导航(从右滑入)
this.navCtrl.navigateForward('/detail');
// 后退导航(从左滑入)
this.navCtrl.navigateBack('/home');
// 根页面(淡入)
this.navCtrl.navigateRoot('/login');
七、导航最佳实践 #
7.1 导航结构 #
text
推荐导航结构:
├── /tabs
│ ├── /tabs/home
│ ├── /tabs/search
│ └── /tabs/profile
├── /auth
│ ├── /auth/login
│ └── /auth/register
├── /detail/:id
└── /settings
7.2 参数传递选择 #
| 方式 | 适用场景 | 特点 |
|---|---|---|
| 路径参数 | 必需参数 | URL可见、可收藏 |
| 查询参数 | 可选参数 | URL可见、可分享 |
| 路由状态 | 复杂对象 | URL不可见 |
| 服务共享 | 跨组件共享 | 全局可访问 |
7.3 返回处理建议 #
typescript
// 推荐:使用ionViewWillEnter刷新
ionViewWillEnter() {
this.loadData();
}
// 不推荐:在ngOnInit中刷新
ngOnInit() {
this.loadData(); // 返回时不会执行
}
八、总结 #
8.1 导航要点 #
| 要点 | 说明 |
|---|---|
| 页面跳转 | routerLink、Router.navigate、NavController |
| 参数传递 | 路径参数、查询参数、路由状态 |
| 返回处理 | ion-back-button、NavController.back() |
| 生命周期 | ionViewWillEnter/Leave |
| 导航动画 | 前进、后退、根页面 |
9.2 下一步 #
掌握了页面导航后,接下来让我们学习 Tabs导航,了解Ionic的标签页导航系统!
最后更新:2026-03-28