Ionic Tabs导航 #
一、Tabs概述 #
1.1 Tabs结构 #
text
Tabs结构
│
├── Tabs容器
│ ├── ion-tabs
│ └── ion-tab-bar
│
├── Tab按钮
│ └── ion-tab-button
│
└── Tab页面
├── Tab1页面
├── Tab2页面
└── Tab3页面
1.2 Tabs特点 #
| 特点 | 说明 |
|---|---|
| 底部导航 | 符合移动端习惯 |
| 状态保持 | 切换时保持页面状态 |
| 独立导航 | 每个Tab独立导航栈 |
| 徽章支持 | 可显示未读数量 |
二、基本Tabs配置 #
2.1 Tabs页面 #
html
<!-- tabs/tabs.page.html -->
<ion-tabs>
<ion-tab-bar slot="bottom">
<ion-tab-button tab="home">
<ion-icon name="home"></ion-icon>
<ion-label>首页</ion-label>
</ion-tab-button>
<ion-tab-button tab="search">
<ion-icon name="search"></ion-icon>
<ion-label>搜索</ion-label>
</ion-tab-button>
<ion-tab-button tab="cart">
<ion-icon name="cart"></ion-icon>
<ion-label>购物车</ion-label>
<ion-badge>3</ion-badge>
</ion-tab-button>
<ion-tab-button tab="profile">
<ion-icon name="person"></ion-icon>
<ion-label>我的</ion-label>
</ion-tab-button>
</ion-tab-bar>
</ion-tabs>
2.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: 'cart',
loadChildren: () => import('../cart/cart.module').then(m => m.CartPageModule)
},
{
path: 'profile',
loadChildren: () => import('../profile/profile.module').then(m => m.ProfilePageModule)
},
{
path: '',
redirectTo: '/tabs/home',
pathMatch: 'full'
}
]
},
{
path: '',
redirectTo: '/tabs/home',
pathMatch: 'full'
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class TabsPageRoutingModule {}
2.3 Tabs模块 #
typescript
// tabs/tabs.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import { TabsPage } from './tabs.page';
import { TabsPageRoutingModule } from './tabs.router.module';
@NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
TabsPageRoutingModule
],
declarations: [TabsPage]
})
export class TabsPageModule {}
三、Tab按钮配置 #
3.1 基本Tab按钮 #
html
<ion-tab-button tab="home">
<ion-icon name="home"></ion-icon>
<ion-label>首页</ion-label>
</ion-tab-button>
3.2 带徽章的Tab #
html
<ion-tab-button tab="notifications">
<ion-icon name="notifications"></ion-icon>
<ion-label>通知</ion-label>
<ion-badge color="danger">5</ion-badge>
</ion-tab-button>
3.3 动态徽章 #
html
<ion-tab-button tab="cart">
<ion-icon name="cart"></ion-icon>
<ion-label>购物车</ion-label>
<ion-badge *ngIf="cartCount > 0" color="danger">
{{ cartCount > 99 ? '99+' : cartCount }}
</ion-badge>
</ion-tab-button>
typescript
import { Component } from '@angular/core';
import { CartService } from './cart.service';
@Component({
selector: 'app-tabs',
templateUrl: 'tabs.page.html'
})
export class TabsPage {
cartCount = 0;
constructor(private cartService: CartService) {
this.cartService.cartCount$.subscribe(count => {
this.cartCount = count;
});
}
}
3.4 自定义Tab图标 #
html
<ion-tab-button tab="home">
<ion-icon name="home-outline" class="icon-outline"></ion-icon>
<ion-icon name="home" class="icon-filled"></ion-icon>
<ion-label>首页</ion-label>
</ion-tab-button>
scss
// 选中状态显示实心图标
ion-tab-button {
.icon-filled {
display: none;
}
&.tab-selected {
.icon-outline {
display: none;
}
.icon-filled {
display: block;
}
}
}
四、Tab导航 #
4.1 编程式切换Tab #
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) {}
goToCart() {
this.router.navigate(['/tabs/cart']);
}
goToProfile() {
this.router.navigateByUrl('/tabs/profile');
}
}
4.2 Tab选择事件 #
html
<ion-tabs (ionTabsDidChange)="onTabChange($event)">
<ion-tab-bar slot="bottom">
<!-- tab buttons -->
</ion-tab-bar>
</ion-tabs>
typescript
import { Component } from '@angular/core';
@Component({
selector: 'app-tabs',
templateUrl: 'tabs.page.html'
})
export class TabsPage {
onTabChange(event: any) {
console.log('当前Tab:', event.tab);
}
}
4.3 Tab内导航 #
typescript
// 在Tab内导航到子页面
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) {}
goToDetail(id: string) {
// 导航到详情页(不在Tabs中)
this.router.navigate(['/detail', id]);
}
}
五、嵌套路由 #
5.1 Tab内子路由 #
typescript
// home/home-routing.module.ts
const routes: Routes = [
{
path: '',
component: HomePage
},
{
path: 'category/:id',
component: CategoryPage
},
{
path: 'product/:id',
component: ProductPage
}
];
5.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) {}
goToCategory(id: string) {
this.router.navigate(['/tabs/home/category', id]);
}
goToProduct(id: string) {
this.router.navigate(['/tabs/home/product', id]);
}
}
5.3 子页面返回 #
html
<!-- 子页面返回按钮 -->
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button defaultHref="/tabs/home"></ion-back-button>
</ion-buttons>
<ion-title>产品详情</ion-title>
</ion-toolbar>
</ion-header>
六、Tabs样式定制 #
6.1 Tab栏样式 #
scss
// Tab栏背景
ion-tab-bar {
--background: #ffffff;
--color: #999999;
--color-selected: #3880ff;
height: 60px;
padding-bottom: env(safe-area-inset-bottom);
border-top: 1px solid #e0e0e0;
}
// Tab按钮样式
ion-tab-button {
--color: #999999;
--color-selected: #3880ff;
--color-focused: #3880ff;
--padding-top: 8px;
--padding-bottom: 8px;
ion-icon {
font-size: 24px;
margin-bottom: 4px;
}
ion-label {
font-size: 12px;
}
}
6.2 顶部Tab栏 #
html
<ion-tabs>
<ion-tab-bar slot="top">
<ion-tab-button tab="tab1">
<ion-label>标签1</ion-label>
</ion-tab-button>
<ion-tab-button tab="tab2">
<ion-label>标签2</ion-label>
</ion-tab-button>
</ion-tab-bar>
</ion-tabs>
6.3 自定义Tab栏 #
html
<ion-tabs>
<ion-tab-bar slot="bottom" class="custom-tab-bar">
<ion-tab-button tab="home" class="custom-tab-button">
<div class="tab-icon">
<ion-icon name="home"></ion-icon>
</div>
<ion-label>首页</ion-label>
</ion-tab-button>
<!-- 中间凸起按钮 -->
<ion-tab-button tab="add" class="center-button">
<div class="add-icon">
<ion-icon name="add"></ion-icon>
</div>
</ion-tab-button>
<ion-tab-button tab="profile" class="custom-tab-button">
<div class="tab-icon">
<ion-icon name="person"></ion-icon>
</div>
<ion-label>我的</ion-label>
</ion-tab-button>
</ion-tab-bar>
</ion-tabs>
scss
.custom-tab-bar {
height: 70px;
padding-bottom: env(safe-area-inset-bottom);
}
.center-button {
--color: #ffffff;
.add-icon {
width: 50px;
height: 50px;
background: #3880ff;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-top: -25px;
box-shadow: 0 4px 12px rgba(56, 128, 255, 0.3);
ion-icon {
font-size: 28px;
color: #ffffff;
}
}
}
七、Tab状态管理 #
7.1 保持Tab状态 #
typescript
// Ionic默认保持Tab状态
// 每个Tab有独立的导航栈
// 首页
@Component({
selector: 'app-home',
templateUrl: 'home.page.html'
})
export class HomePage implements OnInit {
items: any[] = [];
scrollPosition = 0;
ngOnInit() {
this.loadData();
}
ionViewWillLeave() {
// 保存滚动位置
this.scrollPosition = this.getScrollPosition();
}
ionViewWillEnter() {
// 恢复滚动位置
this.scrollToPosition(this.scrollPosition);
}
}
7.2 Tab数据刷新 #
typescript
import { Component } from '@angular/core';
@Component({
selector: 'app-home',
templateUrl: 'home.page.html'
})
export class HomePage {
// 每次进入Tab时刷新
ionViewWillEnter() {
this.refreshData();
}
async refreshData() {
// 刷新数据
}
}
八、最佳实践 #
8.1 Tabs数量 #
text
推荐:3-5个Tab
- 太少:浪费空间
- 太多:难以点击
8.2 Tab图标选择 #
text
推荐:
- 使用系统图标
- 保持风格一致
- 语义清晰
不推荐:
- 混用不同风格图标
- 使用过于复杂的图标
8.3 Tab标签文字 #
text
推荐:
- 简短明确(2-4个字)
- 统一字数
- 语义清晰
不推荐:
- 过长的标签文字
- 中英文混用
九、总结 #
9.1 Tabs要点 #
| 要点 | 说明 |
|---|---|
| Tabs配置 | ion-tabs + ion-tab-bar |
| Tab按钮 | ion-tab-button |
| 路由配置 | 子路由映射 |
| 嵌套路由 | Tab内子页面 |
| 样式定制 | CSS变量 + 自定义样式 |
9.2 下一步 #
掌握了Tabs导航后,接下来让我们学习 高级导航,了解Ionic的高级导航技巧!
最后更新:2026-03-28