Ionic数据展示组件 #
一、列表组件(List) #
1.1 基本用法 #
html
<!-- 基本列表 -->
<ion-list>
<ion-item>
<ion-label>项目一</ion-label>
</ion-item>
<ion-item>
<ion-label>项目二</ion-label>
</ion-item>
<ion-item>
<ion-label>项目三</ion-label>
</ion-item>
</ion-list>
1.2 列表项样式 #
html
<!-- 带图标的列表项 -->
<ion-list>
<ion-item>
<ion-icon name="mail" slot="start"></ion-icon>
<ion-label>邮件</ion-label>
</ion-item>
<ion-item>
<ion-icon name="call" slot="start"></ion-icon>
<ion-label>电话</ion-label>
</ion-item>
</ion-list>
<!-- 带头像的列表项 -->
<ion-list>
<ion-item>
<ion-avatar slot="start">
<img src="avatar.jpg">
</ion-avatar>
<ion-label>
<h2>用户名</h2>
<p>用户描述</p>
</ion-label>
</ion-item>
</ion-list>
<!-- 带缩略图的列表项 -->
<ion-list>
<ion-item>
<ion-thumbnail slot="start">
<img src="image.jpg">
</ion-thumbnail>
<ion-label>
<h2>标题</h2>
<p>描述</p>
</ion-label>
</ion-item>
</ion-list>
1.3 可滑动列表项 #
html
<ion-list>
<ion-item-sliding>
<ion-item>
<ion-label>可滑动项目</ion-label>
</ion-item>
<ion-item-options side="start">
<ion-item-option color="primary">
<ion-icon name="archive"></ion-icon>
归档
</ion-item-option>
</ion-item-options>
<ion-item-options side="end">
<ion-item-option color="danger">
<ion-icon name="trash"></ion-icon>
删除
</ion-item-option>
<ion-item-option color="warning">
<ion-icon name="star"></ion-icon>
收藏
</ion-item-option>
</ion-item-options>
</ion-item-sliding>
</ion-list>
1.4 分组列表 #
html
<ion-list>
<ion-item-divider>
<ion-label>组一</ion-label>
</ion-item-divider>
<ion-item>项目1</ion-item>
<ion-item>项目2</ion-item>
<ion-item-divider>
<ion-label>组二</ion-label>
</ion-item-divider>
<ion-item>项目3</ion-item>
<ion-item>项目4</ion-item>
</ion-list>
1.5 列表头部 #
html
<ion-list>
<ion-list-header>
<ion-label>设置</ion-label>
</ion-list-header>
<ion-item>
<ion-label>通知</ion-label>
<ion-toggle></ion-toggle>
</ion-item>
<ion-item>
<ion-label>深色模式</ion-label>
<ion-toggle></ion-toggle>
</ion-item>
</ion-list>
1.6 动态列表 #
typescript
// 组件
export class MyPage {
items = [
{ id: 1, name: '项目一', description: '描述一' },
{ id: 2, name: '项目二', description: '描述二' },
{ id: 3, name: '项目三', description: '描述三' }
];
deleteItem(item: any) {
const index = this.items.indexOf(item);
this.items.splice(index, 1);
}
}
html
<!-- 模板 -->
<ion-list>
<ion-item-sliding *ngFor="let item of items">
<ion-item [routerLink]="['/detail', item.id]">
<ion-label>
<h2>{{ item.name }}</h2>
<p>{{ item.description }}</p>
</ion-label>
</ion-item>
<ion-item-options side="end">
<ion-item-option color="danger" (click)="deleteItem(item)">
删除
</ion-item-option>
</ion-item-options>
</ion-item-sliding>
</ion-list>
二、卡片组件(Card) #
2.1 基本用法 #
html
<!-- 基本卡片 -->
<ion-card>
<ion-card-header>
<ion-card-title>卡片标题</ion-card-title>
<ion-card-subtitle>卡片副标题</ion-card-subtitle>
</ion-card-header>
<ion-card-content>
这是卡片内容区域。
</ion-card-content>
</ion-card>
2.2 带图片的卡片 #
html
<ion-card>
<ion-img src="image.jpg"></ion-img>
<ion-card-header>
<ion-card-title>图片卡片</ion-card-title>
</ion-card-header>
<ion-card-content>
这是带图片的卡片内容。
</ion-card-content>
</ion-card>
2.3 卡片按钮 #
html
<ion-card>
<ion-card-header>
<ion-card-title>操作卡片</ion-card-title>
</ion-card-header>
<ion-card-content>
<p>卡片描述内容</p>
</ion-card-content>
<ion-button fill="clear">查看详情</ion-button>
</ion-card>
2.4 卡片列表 #
html
<ion-card *ngFor="let item of items">
<ion-card-header>
<ion-card-title>{{ item.title }}</ion-card-title>
</ion-card-header>
<ion-card-content>
{{ item.content }}
</ion-card-content>
</ion-card>
2.5 社交卡片 #
html
<ion-card>
<ion-item>
<ion-avatar slot="start">
<img src="avatar.jpg">
</ion-avatar>
<ion-label>
<h2>用户名</h2>
<p>2小时前</p>
</ion-label>
<ion-button fill="clear" slot="end">
<ion-icon name="ellipsis-horizontal"></ion-icon>
</ion-button>
</ion-item>
<ion-img src="post-image.jpg"></ion-img>
<ion-card-content>
<p>这是发布的动态内容...</p>
</ion-card-content>
<ion-row>
<ion-col>
<ion-button fill="clear" expand="block">
<ion-icon name="heart-outline" slot="start"></ion-icon>
点赞
</ion-button>
</ion-col>
<ion-col>
<ion-button fill="clear" expand="block">
<ion-icon name="chatbubble-outline" slot="start"></ion-icon>
评论
</ion-button>
</ion-col>
<ion-col>
<ion-button fill="clear" expand="block">
<ion-icon name="share-outline" slot="start"></ion-icon>
分享
</ion-button>
</ion-col>
</ion-row>
</ion-card>
2.6 卡片样式 #
scss
ion-card {
--background: #ffffff;
margin: 16px;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
ion-card-header {
padding: 16px;
ion-card-title {
font-size: 18px;
font-weight: bold;
color: #333333;
}
ion-card-subtitle {
font-size: 14px;
color: #999999;
}
}
ion-card-content {
padding: 16px;
font-size: 14px;
color: #666666;
}
}
三、网格组件(Grid) #
3.1 基本用法 #
html
<ion-grid>
<ion-row>
<ion-col>
<div>列1</div>
</ion-col>
<ion-col>
<div>列2</div>
</ion-col>
<ion-col>
<div>列3</div>
</ion-col>
</ion-row>
</ion-grid>
3.2 列宽设置 #
html
<ion-grid>
<ion-row>
<ion-col size="6">
<div>占6列</div>
</ion-col>
<ion-col size="3">
<div>占3列</div>
</ion-col>
<ion-col size="3">
<div>占3列</div>
</ion-col>
</ion-row>
</ion-grid>
3.3 响应式列宽 #
html
<ion-grid>
<ion-row>
<!-- 不同屏幕尺寸不同宽度 -->
<ion-col size="12" size-sm="6" size-md="4" size-lg="3">
<div>响应式列</div>
</ion-col>
<ion-col size="12" size-sm="6" size-md="4" size-lg="3">
<div>响应式列</div>
</ion-col>
<ion-col size="12" size-sm="6" size-md="4" size-lg="3">
<div>响应式列</div>
</ion-col>
<ion-col size="12" size-sm="6" size-md="4" size-lg="3">
<div>响应式列</div>
</ion-col>
</ion-row>
</ion-grid>
3.4 偏移量 #
html
<ion-grid>
<ion-row>
<ion-col size="4" offset="4">
<div>偏移4列</div>
</ion-col>
</ion-row>
<ion-row>
<ion-col size="3" offset="3">
<div>偏移3列</div>
</ion-col>
<ion-col size="3">
<div>正常列</div>
</ion-col>
</ion-row>
</ion-grid>
3.5 对齐方式 #
html
<!-- 水平对齐 -->
<ion-grid>
<ion-row class="ion-justify-content-center">
<ion-col size="4">
<div>居中</div>
</ion-col>
</ion-row>
<ion-row class="ion-justify-content-end">
<ion-col size="4">
<div>右对齐</div>
</ion-col>
</ion-row>
<ion-row class="ion-justify-content-around">
<ion-col size="3">
<div>分散</div>
</ion-col>
<ion-col size="3">
<div>分散</div>
</ion-col>
</ion-row>
</ion-grid>
<!-- 垂直对齐 -->
<ion-grid>
<ion-row class="ion-align-items-center" style="height: 200px;">
<ion-col>
<div>垂直居中</div>
</ion-col>
</ion-row>
</ion-grid>
3.6 网格样式 #
scss
ion-grid {
--ion-grid-padding: 16px;
--ion-grid-column-padding: 12px;
}
ion-col {
background: #f5f5f5;
border: 1px solid #e0e0e0;
padding: 12px;
text-align: center;
}
四、虚拟滚动(Virtual Scroll) #
4.1 基本用法 #
html
<ion-content>
<ion-virtual-scroll [items]="items" [itemHeight]="56">
<ion-item *virtualItem="let item">
<ion-label>{{ item.name }}</ion-label>
</ion-item>
</ion-virtual-scroll>
</ion-content>
4.2 复杂列表项 #
html
<ion-content>
<ion-virtual-scroll [items]="items" [itemHeight]="80">
<ion-item *virtualItem="let item">
<ion-avatar slot="start">
<img [src]="item.avatar">
</ion-avatar>
<ion-label>
<h2>{{ item.name }}</h2>
<p>{{ item.email }}</p>
</ion-label>
</ion-item>
</ion-virtual-scroll>
</ion-content>
4.3 分组虚拟滚动 #
html
<ion-content>
<ion-virtual-scroll
[items]="items"
[itemHeight]="getHeight"
[headerFn]="getHeader">
<ion-item-divider *virtualHeader="let header">
{{ header }}
</ion-item-divider>
<ion-item *virtualItem="let item">
<ion-label>{{ item.name }}</ion-label>
</ion-item>
</ion-virtual-scroll>
</ion-content>
typescript
// 组件
export class MyPage {
items = [
{ name: 'Alice', group: 'A' },
{ name: 'Bob', group: 'B' },
{ name: 'Charlie', group: 'C' }
];
getHeight(item: any) {
return item.isHeader ? 40 : 56;
}
getHeader(item: any) {
return item.group;
}
}
五、无限滚动(Infinite Scroll) #
5.1 基本用法 #
html
<ion-content>
<ion-list>
<ion-item *ngFor="let item of items">
{{ item.name }}
</ion-item>
</ion-list>
<ion-infinite-scroll (ionInfinite)="loadMore($event)">
<ion-infinite-scroll-content
loadingSpinner="crescent"
loadingText="加载更多...">
</ion-infinite-scroll-content>
</ion-infinite-scroll>
</ion-content>
typescript
// 组件
export class MyPage {
items: any[] = [];
page = 1;
constructor(private api: ApiService) {
this.loadData();
}
async loadData() {
const data = await this.api.getItems(this.page);
this.items = [...this.items, ...data];
}
async loadMore(event: any) {
this.page++;
await this.loadData();
event.target.complete();
// 没有更多数据时禁用
if (this.items.length >= 100) {
event.target.disabled = true;
}
}
}
5.2 无限滚动样式 #
scss
ion-infinite-scroll-content {
--color: #3880ff;
min-height: 60px;
}
六、下拉刷新(Refresher) #
6.1 基本用法 #
html
<ion-content>
<ion-refresher slot="fixed" (ionRefresh)="doRefresh($event)">
<ion-refresher-content
pullingIcon="arrow-down"
pullingText="下拉刷新"
refreshingSpinner="crescent"
refreshingText="刷新中...">
</ion-refresher-content>
</ion-refresher>
<ion-list>
<ion-item *ngFor="let item of items">
{{ item.name }}
</ion-item>
</ion-list>
</ion-content>
typescript
// 组件
export class MyPage {
items: any[] = [];
async doRefresh(event: any) {
this.page = 1;
await this.loadData();
event.target.complete();
}
}
6.2 自定义刷新内容 #
html
<ion-refresher slot="fixed" (ionRefresh)="doRefresh($event)">
<ion-refresher-content
pullingIcon="refresh"
pullingText="下拉刷新"
refreshingSpinner="dots"
refreshingText="正在刷新...">
</ion-refresher-content>
</ion-refresher>
七、幻灯片组件(Slides) #
7.1 基本用法 #
html
<ion-slides pager="true">
<ion-slide>
<h1>幻灯片 1</h1>
</ion-slide>
<ion-slide>
<h1>幻灯片 2</h1>
</ion-slide>
<ion-slide>
<h1>幻灯片 3</h1>
</ion-slide>
</ion-slides>
7.2 自动播放 #
html
<ion-slides
[options]="slideOpts"
(ionSlideDidChange)="onSlideChange($event)">
<ion-slide>
<img src="banner1.jpg">
</ion-slide>
<ion-slide>
<img src="banner2.jpg">
</ion-slide>
<ion-slide>
<img src="banner3.jpg">
</ion-slide>
</ion-slides>
typescript
// 组件
export class MyPage {
slideOpts = {
initialSlide: 0,
speed: 400,
autoplay: {
delay: 3000,
disableOnInteraction: false
},
loop: true
};
onSlideChange(event: any) {
console.log('幻灯片切换');
}
}
7.3 幻灯片样式 #
scss
ion-slides {
height: 200px;
}
ion-slide {
display: flex;
align-items: center;
justify-content: center;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
八、完整示例 #
8.1 新闻列表 #
typescript
// 组件
export class NewsPage {
news: any[] = [];
page = 1;
isLoading = false;
constructor(private api: ApiService) {}
ionViewWillEnter() {
this.loadNews();
}
async loadNews() {
this.isLoading = true;
const data = await this.api.getNews(this.page);
this.news = [...this.news, ...data];
this.isLoading = false;
}
async doRefresh(event: any) {
this.page = 1;
this.news = [];
await this.loadNews();
event.target.complete();
}
async loadMore(event: any) {
this.page++;
await this.loadNews();
event.target.complete();
}
async deleteNews(item: any) {
const index = this.news.indexOf(item);
this.news.splice(index, 1);
}
}
html
<!-- 模板 -->
<ion-header>
<ion-toolbar>
<ion-title>新闻列表</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-refresher slot="fixed" (ionRefresh)="doRefresh($event)">
<ion-refresher-content></ion-refresher-content>
</ion-refresher>
<ion-card *ngFor="let item of news" [routerLink]="['/news', item.id]">
<ion-img [src]="item.image"></ion-img>
<ion-card-header>
<ion-card-title>{{ item.title }}</ion-card-title>
<ion-card-subtitle>{{ item.date }}</ion-card-subtitle>
</ion-card-header>
<ion-card-content>
{{ item.summary }}
</ion-card-content>
</ion-card>
<ion-infinite-scroll (ionInfinite)="loadMore($event)">
<ion-infinite-scroll-content></ion-infinite-scroll-content>
</ion-infinite-scroll>
</ion-content>
九、总结 #
9.1 组件对比 #
| 组件 | 用途 | 特点 |
|---|---|---|
| List | 列表展示 | 灵活、可滑动 |
| Card | 卡片展示 | 信息丰富 |
| Grid | 网格布局 | 响应式 |
| Virtual Scroll | 大数据列表 | 性能优化 |
| Infinite Scroll | 无限加载 | 分页加载 |
| Refresher | 下拉刷新 | 更新数据 |
| Slides | 幻灯片 | 轮播展示 |
9.2 下一步 #
掌握了数据展示组件后,接下来让我们学习 主题与样式,了解Ionic的主题定制!
最后更新:2026-03-28