Ionic 3应用外部图片加载:寻求加载完成前显示Spinner的可行方案
在Ionic 3中实现图片加载前显示Spinner的方案
我来分享几个亲测有效的方案,不用依赖那些难配置的缓存插件,纯用Ionic和Angular原生就能搞定,完全适配ion-card、ion-item、ion-slides这些场景:
方案1:原生HTML事件 + Ionic Spinner(快速实现)
这是最直接的方法,利用图片的load和error事件来控制Spinner的显示隐藏,适合快速在单个页面里实现。
模板代码(以ion-card为例)
<ion-card> <div class="image-wrap"> <!-- 默认显示Spinner --> <ion-spinner name="crescent" *ngIf="!avatarLoaded"></ion-spinner> <!-- 图片加载完成后显示,加载失败也可以做处理 --> <img src="https://your-external-image-url.jpg" (load)="avatarLoaded = true" (error)="handleLoadError()" [hidden]="!avatarLoaded" /> </div> <ion-card-content> 这是卡片内容 </ion-card-content> </ion-card>
组件TS代码
import { Component } from '@angular/core'; @Component({ selector: 'app-profile-card', templateUrl: './profile-card.component.html', styleUrls: ['./profile-card.component.scss'] }) export class ProfileCardComponent { avatarLoaded = false; handleLoadError() { // 加载失败时,可以显示占位图,或者直接隐藏Spinner this.avatarLoaded = true; // 也可以设置一个error标志,显示错误提示 // this.loadError = true; } }
样式(让Spinner居中)
.image-wrap { position: relative; width: 100%; height: 220px; /* 根据你的需求设置高度 */ overflow: hidden; ion-spinner { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } img { width: 100%; height: 100%; object-fit: cover; } }
方案2:自定义图片加载组件(高复用性)
如果你的应用很多地方都需要加载图片,写个可复用的组件更省心,不用重复写逻辑。
1. 创建app-image-loader组件
执行命令生成组件:
ionic g component image-loader
2. 组件模板
<div class="image-loader-container"> <ion-spinner name="dots" *ngIf="!isLoaded && !hasError"></ion-spinner> <img [src]="imageUrl" (load)="isLoaded = true" (error)="hasError = true" [hidden]="!isLoaded || hasError" /> <!-- 加载失败的占位内容 --> <div *ngIf="hasError" class="error-block"> <ion-icon name="image"></ion-icon> <p>图片加载失败</p> </div> </div>
3. 组件TS代码
import { Component, Input } from '@angular/core'; @Component({ selector: 'app-image-loader', templateUrl: './image-loader.component.html', styleUrls: ['./image-loader.component.scss'] }) export class ImageLoaderComponent { @Input() imageUrl: string; // 接收外部传入的图片地址 isLoaded = false; hasError = false; }
4. 在页面中复用组件
不管是ion-card、ion-item还是ion-slides,直接用这个组件就行:
<!-- ion-card里用 --> <ion-card> <app-image-loader [imageUrl]="'https://example.com/image1.jpg'"></app-image-loader> <ion-card-content>卡片内容</ion-card-content> </ion-card> <!-- ion-item里用 --> <ion-item> <app-image-loader [imageUrl]="'https://example.com/image2.jpg'"></app-image-loader> <ion-label>商品名称</ion-label> </ion-item> <!-- ion-slides里用 --> <ion-slides> <ion-slide *ngFor="let slide of slides"> <app-image-loader [imageUrl]="slide.imageUrl"></app-image-loader> </ion-slide> </ion-slides>
方案3:结合Ionic的ion-img组件(适配懒加载)
Ionic 3的ion-img本身支持懒加载,并且提供了专属的加载事件ionImgDidLoad和错误事件ionImgError,比原生img更适配Ionic的场景:
<ion-slides> <ion-slide *ngFor="let item of slideItems"> <div class="slide-image-wrap"> <ion-spinner *ngIf="!item.loaded"></ion-spinner> <ion-img [src]="item.imageUrl" (ionImgDidLoad)="item.loaded = true" (ionImgError)="item.loaded = true" [hidden]="!item.loaded" ></ion-img> </div> </ion-slide> </ion-slides>
对应的TS代码
slideItems = [ { imageUrl: 'https://example.com/slide1.jpg', loaded: false }, { imageUrl: 'https://example.com/slide2.jpg', loaded: false }, // ...更多轮播图 ];
几个注意点
- 对于
ion-slides,因为会预加载部分slide,所以每个slide的图片都要单独维护加载状态,比如用数组对象的loaded属性 - 如果图片数量较多,建议开启
ion-img的懒加载,或者手动实现滚动加载,避免一次性加载太多图片导致性能问题 - 之前的缓存插件没成功,可能是配置或者版本兼容问题,上面的方案都不依赖第三方插件,稳定性更高
内容的提问来源于stack exchange,提问作者Deemantha
相关产品推荐
相关产品推荐

