前言:
在开发响应式鸿蒙应用时,我们实现了基于网络状态和数据的动态页面展示方案。虽然单个页面的修改可以在当前页面完成,但需要确保整个项目的所有界面都保持一致的响应逻辑和用户体验。接下来我们进行封装一个状态页。
一、需求输入
我们按照以下的需求写一个鸿蒙的状态页:
状态分类:网络层异常,数据层异常,服务层异常
交互设计规范:网络异常界面(提示暂无网络),空数据界面(提示暂无数据,请稍后再试),服务异常界面(服务器开小差)
二、技术 WrappedBuilder:
WrappedBuilder是鸿蒙ArkUI框架中用于封装全局@Builder函数的工具类,主要解决构建器动态调用的技术难题
三、实现方案
1,使用PageStatus进行管理page状态
2,使用contentBuilder展示有数据界面
3,loadingStatusBuilder展示加载界面
4,noContentBuilder展示无数据界面
5,errorStatusBuilder展示错误数据界面
6,使用StatusManager进行管理界面
封装的组件:
@Component
export struct StatusComponent {
@Prop pageHeight: Length = "100%" //page 高度
@Prop pageWidth: Length = "100%" //page 宽度
@Require @BuilderParam contentBuilder: () => void; //内容布局
@Prop pageStatus: PageStatus = PageStatus.Undefined //page状态
@BuilderParam loadingStatusBuilder: () => void //自定义loading Builder
@BuilderParam noContentBuilder: () => void //自定义无内容Builder
@BuilderParam errorStatusBuilder: () => void //自定义错误Builder
outSideControlStatus: boolean = false
errorEvent?: () => void //全局状态下的error Builder点击回调
aboutToAppear() {
//无网界面
if (!this.outSideControlStatus && !CommonNetWorkUtils.isNetworkAvailable()) {
this.pageStatus = PageStatus.NetError
}
}
build() {
Stack() {
if (this.pageStatus == PageStatus.Loading) {
if (this.loadingStatusBuilder) {
this.loadingStatusBuilder()
} else {
StatusManager.getInstance().getLoadingWrapBuilder()?.builder()
}
} else if (this.pageStatus == PageStatus.NoContent) {
if (this.noContentBuilder) {
this.noContentBuilder()
} else {
StatusManager.getInstance().getNoContentWrapBuilder()?.builder()
}
} else if (this.pageStatus == PageStatus.NetError) {
if (this.errorStatusBuilder) {
this.errorStatusBuilder()
} else {
StatusManager.getInstance().getErrorWrapBuilder()?.builder(this.errorEvent)
}
} else {
this.contentBuilder()
}
}
.height(this.pageHeight)
.width(this.pageWidth)
.align(Alignment.TopStart)
}
}
管理状态界面
export class StatusManager {
private static mInstance: StatusManager
private constructor() {
}
public static getInstance(): StatusManager {
if (StatusManager.mInstance == null) {
StatusManager.mInstance = new StatusManager()
}
return StatusManager.mInstance
}
private loadingWrapBuilder?: WrappedBuilder<[]>
private noContentWrapBuilder?: WrappedBuilder<[]>
private errorWrapBuilder?: WrappedBuilder<[() => void]>
/**
* 设置加载中包装构建器
* @param loadingWrapBuilder 加载中包装构建器
*/
public setLoadingWrapBuilder(loadingWrapBuilder: WrappedBuilder<[]>): StatusManager {
this.loadingWrapBuilder = loadingWrapBuilder
return this
}
/**
* 设置无内容包装构建器
* @param noContentWrapBuilder 无内容包装构建器
*/
public setNoContentWrapBuilder(noContentWrapBuilder: WrappedBuilder<[]>): StatusManager {
this.noContentWrapBuilder = noContentWrapBuilder
return this
}
/**
* 设置错误包装构建器
* @param errorWrapBuilder 错误包装构建器
*/
public setErrorWrapBuilder(errorWrapBuilder: WrappedBuilder<[() => void]>): StatusManager {
this.errorWrapBuilder = errorWrapBuilder
return this
}
/**
* 获取加载中包装构建器
*/
public getLoadingWrapBuilder(): WrappedBuilder<[]> | undefined {
return this.loadingWrapBuilder;
}
/**
* 获取无内容包装构建器
*/
public getNoContentWrapBuilder(): WrappedBuilder<[]> | undefined {
return this.noContentWrapBuilder;
}
/**
* 获取错误包装构建器
*/
public getErrorWrapBuilder(): WrappedBuilder<[() => void]> | undefined {
return this.errorWrapBuilder;
}
}
设置状态界面
StatusManager.getInstance()
.setLoadingWrapBuilder(wrapBuilder(DefaultLoadingComponent))
.setNoContentWrapBuilder(wrapBuilder(DefaultEmptyComponent))
.setErrorWrapBuilder(wrapBuilder(DefaultNoNetComponent))
项目中使用状态界面组件:
StatusComponent({
pageStatus: this.loadingState,
pageWidth: FULL_WIDTH,
pageHeight:FULL_HEIGHT,
contentBuilder: () => {
this.contentView()
},
noContentBuilder:()=>{
this.emptyView()
}
})