1、ef_rcp简介:是基于rcp封装的网络请求相关包.提供了rcp的上传,下载,post,get,cancel,delete,put等操作。
ef_rcp出处ef_rcp;
2、PullToRefresh简介:采用的装饰器有V1,V2,作者紧跟期间的潮流。功能上:实现垂直列表下拉刷新,上拉加载,横向列表左拉刷新,右拉加载等操作。
PullToRefresh出处PullToRefresh;
3、SmartDialog简介:鸿蒙版本的SmartDialog,优雅,极简的用法;非UI地域内利用,自界说Component;返回事件处理,优化的跨页面交互;多弹窗本领,多位置弹窗:上下左右中间;
定位弹窗:自动定位目的Component;极简用法的loading弹窗。
SmartDialog出处SmartDialog;
非常感谢大佬们出的库,方便我们开发,提高我们开发效率,更具体的先容和利用请看官方出处。
其它
RCP官网
RCP网络请求配置
1、增长BaseResponse。
- export class BaseResponse<T> {
- //成功失败标识
- private success: boolean;
- //返回提示信息
- private msg: string;
- //响应编码
- private code: string | number;
- //返回数据
- private data: T;
- /**
- * 构造函数
- * @param success 是否成功标识
- * @param msg 提示消息
- * @param data 数据
- */
- constructor(success: boolean, msg: string, data: T, code: string | number) {
- this.msg = msg;
- this.success = success;
- this.code = code;
- this.data = data;
- }
- /**
- * 创建空实例
- * @returns
- */
- static create(): BaseResponse<string> {
- let baseResponse = new BaseResponse<string>(true, '', '', 200);
- return baseResponse;
- }
- /**
- * 成功-只包含消息
- * @param msg 提示消息
- * @returns
- */
- static OK(msg: string): BaseResponse<string> {
- let baseResponse = new BaseResponse<string>(true, msg, '', 200);
- return baseResponse;
- }
- /**
- * 成功-包含单行数据
- * @param msg 提示消息
- * @param data 单行数据
- * @returns
- */
- static OKByData<T>(msg: string, data: T): BaseResponse<T> {
- let dto = new BaseResponse<T>(true, msg, data, 200);
- return dto;
- }
- /**
- * 失败-包含提示消息
- * @param msg 提示消息
- * @returns
- */
- static Error(msg: string): BaseResponse<string> {
- let dto = new BaseResponse<string>(false, msg, '', 400);
- return dto;
- }
- /**
- * 失败-包含单行数据
- * @param msg 提示消息
- * @param data 单行数据
- * @returns
- */
- static ErrorByData<T>(msg: string, data: T): BaseResponse<T> {
- let dto = new BaseResponse<T>(false, msg, data, 400);
- return dto;
- }
- public setSuccess(success: boolean) {
- this.success = success;
- }
- public getSuccess(): boolean {
- return this.success;
- }
- public getCode(): string | number {
- return this.code;
- }
- public setCode(code: string | number) {
- this.code = code;
- }
- public getMsg(): string {
- return this.msg;
- }
- public setMsg(msg: string) {
- this.msg = msg;
- }
- public getData(): T {
- return this.data;
- }
- public setData(data: T) {
- this.data = data;
- }
- }
复制代码 2、增长不同接口返回不同数据结构的响应内容拦截器,保持输出划一。
官方拦截器链接
2.1.思量几种常见数据返回的
- // {"code":200,"message":"success","data":{"isCheck":"0"}}
- // {"status":"1","msg":"success","result":{"data":{"ticket":"ST-2c2fd56bad7f49259edbb4b00ccc6cbe"}}}
复制代码 2.2.修改响应内容
- const response = await next.handle(context);
复制代码
- 把接口返回不同的code,msg,data转为划一。例子中code为200和0代表成功,可根据公司规定修改。
- 思量几种常见数据返回的
- // {"code":200,"message":"success","data":{"isCheck":"0"}}
- // {"status":"1","msg":"success","result":{"data":{"ticket":"xxxxx"}}}
- // {"data": ..., "errorCode": 0, "errorMsg": ""} errorCode = 0 代表执行成功.errorCode = -1001 代表登录失效,需要重新登录
复制代码- //转换成object
- let result = response.toJSON();
- //考虑几种常见数据返回的
- // {"code":200,"message":"success","data":{"isCheck":"0"}}
- // {"status":"1","msg":"success","result":{"data":{"ticket":"ST-2c2fd56bad7f49259edbb4b00ccc6cbe"}}}
- // {"data": ..., "errorCode": 0, "errorMsg": ""} errorCode = 0 代表执行成功.errorCode = -1001 代表登录失效,需要重新登录
- //1.成功失败标识
- let success: boolean = true;
- //2.返回的消息提示
- let message: string = '';
- //3.返回的数据
- let data: Record<string, Object> = {};
- //4.返回请求状态码
- let code = response.statusCode + '';
- if (result) {
- Object.entries(result).forEach((item: object) => {
- if (["errorCode", "code", "status"].includes(String(item[0]))) {
- code = String(item[1])
- success = disposeCode(String(item[1]));
- }
- if (["errorMsg", "message", "msg"].includes(String(item[0]))) {
- message = String(item[1]);
- }
- if (["data", "result"].includes(String(item[0]))) {
- data = item[1];
- }
- })
- }
- // HTTP status code
- if (response.statusCode != 200) {
- success = false;
- message = (response.toString() as string) ? response.toString() as string : "网络错误";
- }
复制代码
- if (["code", "status"].includes(String(item[0]))) {
- code = String(item[1])
- success = disposeCode(String(item[1]));
- }
复制代码
- disposeCode的作用,处理不同接口返回的码
- /** 处理不同接口返回的码.errorCode = 0 || code==200 || status==1 为成功 */
- export function disposeCode(s: string): boolean {
- let isSuccess: boolean = false;
- if ("0" == s || "200" == s || "1" == s) {
- isSuccess = true;
- }
- return isSuccess;
- }
复制代码
- let baseResponse = new BaseResponse(success, disposeMsg(code, message), data, code);
复制代码
- disposeMsg的作用,表示处理信息,比如针对于特定的code码,返回指定的msg。
- /** 处理信息 */
- export function disposeMsg(code: string, msg: string): string {
- let message = "";
- switch (code) {
- case '-1001':
- case '401':
- message = "登陆信息过期,请重新登陆";
- break;
- case '403':
- message = "账号异常,请联系客服";
- break;
- case '429':
- message = "您的操作过于频繁,请稍后再试!";
- break;
- case '500':
- message = "服务器错误(500)";
- break;
- default:
- message = `${msg}`;
- }
- const errorCodes = ['401', '403', '429', '500'];
- if (errorCodes.includes(code)) {
- //吐司
- ToastUtil.showToast(message);
- }
- return message;
- }
复制代码
- //对响应修改
- const toReturn: rcp.Response = {
- request: response.request,
- statusCode: response.statusCode,
- headers: response.headers,
- effectiveUrl: response.effectiveUrl,
- body: response.body,
- downloadedTo: response.downloadedTo,
- timeInfo: response.timeInfo,
- httpVersion: response.httpVersion,
- reasonPhrase: response.reasonPhrase,
- toString: () => response.toString(),
- toJSON: () => baseResponse
- };
- return toReturn;
复制代码 3、初始化参数配置,在EntryAbility的onWindowStageCreate写
- // if(运行环境===debug){
- efRcp
- .setBaseURL("https://www.wanandroid.com") //设置请求路径
- .enableLogInterceptor()//设置为false即可关闭
- .setLoadingContent('正在加载中...')//更改loading文本
- .convertError(true)//表示如果response.toJSON()异常时将响应字符串返回,false则表示值返回异常提醒而不返回结果
- .addCommonHeaders({//设置公共头
- "version": `V1.0.0`
- })// .setLoadingImg(wrapBuilder(loadingImg)) //设置loading为gif图片
- .addCustomInterceptors([new ResponseInterceptor()])
- .addSysCodeEvent({//添加统一系统框架级别编码处理逻辑,如超时等
- listener: (code: number) => {
- // Log.d('---------addSysCodeEvent监听事件-----' + code)
- switch (code) {
- case -1001:
- case 401:
- console.log(`xxx : ---跳转登录页面,清空一些数据等`)
- //跳转登录页面,清空一些数据等
- // ZRouter.replacePathByName('LoginPage')
- break;
- }
- }
- })//创建session对象,需要再设置为一系列操作后再调用,否则设置不生效,可在特殊情况处设置其他操作后重新创建session
- .create()//获取统一的session对象,必须在create后调用 .设置了全局的配置比如拦截器 超时时间 session本身的配置 ,需要再次create
- .builder();
- // }
复制代码 4、如何利用,更多具体内容可以参考ef_rcp作者的主页
- post请求为例,例子在 TestNetView 页面
- //登录
- let login = await PhoneService.login({
- 'username': '鸿蒙',
- 'password': '5.0'
- })
- console.log('xxxlogin--' + '' + json.stringify(login))
- if (login.data?.getSuccess()) {
- this.message = json.stringify(login.data.getData())
- console.log('xxxxxdata参数--' + '' + json.stringify(login.data.getData()))
- } else {
- console.log('xxx--' + login.data?.getMsg())
- ToastUtil.showToast(login.data?.getMsg())
- }
-
- PhoneService类
- export class PhoneService {
- static login(query: Record<string, Object>): Promise<EfRcpResponse<BaseResponse<object>>> {
- return efRcpClientApi.post<BaseResponse<object>>({
- url: 'user/login',
- query: query,
- loadingTxt: '正在登录中...',
- loading: false
- });
- }
- }
复制代码
5、自带的loading( 图一 ) 假如不符合可以自界说一个builder,参考下面的弹窗设置。
- 设置自界说loading样式和内容
.setLoadingBuilder(wrapBuilder(loadingNetView))
- /** 目前网络请求不支持传loading文字 */
- @Builder
- function loadingNetView() {
- Column() {
- loadingBuilder()
- }
- .border({
- width: 1,
- radius: 8,
- color: $r('app.color.color_F0F0F0')
- })
- }
- @Builder
- function loadingView(args: ResourceStr = '正在加载中...') {
- loadingBuilder(args)
- }
- @Builder
- function loadingBuilder(args?: ResourceStr) {
- Column() {
- Image($r('app.media.loading_refresh')).width(50).height(50)
- Text(args ? args : '正在加载中...')
- .fontSize(11)
- .fontColor($r('app.color.color_222222'))
- .margin({ top: 11 })
- .maxLines(1)
- .textOverflow({ overflow: TextOverflow.Ellipsis })
- }
- .width(120)
- .height(120)
- .justifyContent(FlexAlign.Center)
- .backgroundColor(Color.White)
- .borderRadius(12)
- }
复制代码
PullToRefresh上下拉刷新配置,采用V2装饰器版本
1、下载安装,目前版本是 “^2.0.1”
- ohpm install @zhongrui/pull_to_refresh_v2
复制代码 2、每个项目的上下拉刷新头部,尾部都不一样,以是我这里采用了个性化定制,请利用RefreshLayout
- @Preview
- @ComponentV2
- export struct TestRefreshView {}
复制代码
- @Builder
- defHeaderView() {
- Stack({ alignContent: Alignment.Center }) {
- if (this.pullDown?.status == PullStatus.PullDown || this.pullDown?.status == PullStatus.Refresh || this.pullDown?.status == PullStatus.PreRefresh) {
- Row() {
- Image($r("app.media.loading_refresh")).width(50).height(40)
- }.width('100%')
- .height(50)
- .justifyContent(FlexAlign.Center)
- } else if (this.pullDown?.status == PullStatus.RefreshSuccess) {
- // Text("刷新成功").textExtend()
- } else if (this.pullDown?.status == PullStatus.RefreshError) {
- Text("刷新失败,请重新尝试").textExtend()
- }
- }.height(50).width("100%")
- }
复制代码
- /** 自定义刷新尾部 */
- @Builder
- defFooterView() {
- Stack({ alignContent: Alignment.Center }) {
- if (this.pullDown?.status == PullStatus.PullUp || this.pullDown?.status == PullStatus.Load || this.pullDown?.status == PullStatus.PreLoad) {
- Row() {
- Image($r("app.media.loading_refresh"))
- .width(24)
- .height(24)
- }.width('100%')
- .height(60)
- .justifyContent(FlexAlign.Center)
- } else if (this.pullDown?.status == PullStatus.LoadSuccess) {
- // Text("加载完成").textExtend()
- } else if (this.pullDown?.status == PullStatus.LoadError) {
- Text('加载失败,请重新尝试').textExtend()
- }
- }.height(50).width("100%")
- }
复制代码
- /** 内容视图 */
- @Builder
- _ContentView() {
- Text("contentView:()=>{your @Builder View}")
- }
复制代码
- /** loading视图 */
- @Builder
- loadingView() {
- this.layout($r('app.media.loading_refresh'), '正在加载...')
- }
复制代码
- /** 空视图 */
- @Builder
- _EmptyView() {
- this.layout($r('app.media.nodata'), '暂无数据')
- }
复制代码
- /** 错误视图 */
- @Builder
- _ErrorView() {
- this.layout($r('app.media.no_network'), '暂无网络,请重新尝试')
- }
复制代码
- /** 视图公用 */
- @Builder
- layout(src: ResourceStr, text: ResourceStr) {
- Column() {
- Image(src).width(48).height(48)
- Text(text).fontSize(12).fontColor($r('app.color.color_999999')).padding(8)
- }.width(CommonConst.FULL_PARENT)
- .height(CommonConst.FULL_PARENT)
- .justifyContent(FlexAlign.Center)
- }
复制代码
- 底部暂无更多(目前只能往上拉才能看到,假如不上拉也能看到,那就自界说一个Item放到最下面)。
- /**
- * 暂无更多
- * @param isV 是否竖向
- */
- @Builder
- defFooterNoMoreView(isV: boolean) {
- Text('没有更多数据了')
- .textAlign(TextAlign.Center)
- .height(isV ? 50 : CommonConst.FULL_PARENT)
- .width(isV ? CommonConst.FULL_PARENT : 50)
- .fontSize(14)
- .fontColor($r('app.color.color_999999'))
- }
- private isVerticalLayout(): boolean {
- return (this.config.isVertical || this.config.horizontalMode == 1 || this.config.horizontalMode == 2)
- }
- }
复制代码
- .edgeEffect(EdgeEffect.None)
复制代码
- BasicDataSource,配合LazyForEach利用,数据太多的话建议用LazyForEach;后期可以看看(Repeat:子组件复用)
- 源代码请看项目中,模块uicomponents /src/main/ets/components/refresh/BasicDataSource
复制代码 3、封装请求返回的数据,更加简洁
- /** 请求接口 */
- async loadData() {
- let data: Array<string> = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20"]
- // let data:string[] = []// 空数据
- this.dataSource.pageRefresh(true, this.pageNum, data.length, data, this.controller,
- (pages: number) => {
- this.pageNum = pages
- })
- }
复制代码- /**
- * 列表页数 处理
- * @param success 成功失败标识
- * @param page 页数
- * @param total 总条数
- * @param data 数据
- * @param controller RefreshController
- * @param pageNums 返回的page
- */
- public pageRefresh(success: boolean, page: number, total: number, data: Array<T>, controller: RefreshController, pageNums: (pages: number) => void) {
- if (success) {
- if (page == 1) {
- this.setNewData(data)
- controller.refreshSuccess()
- pageNums(2)
- if (this.totalCount() == 0) {
- controller.viewEmpty()
- }
- } else {
- this.addAllData(data)
- controller.loadSuccess()
- pageNums(data.length == 0 ? page : (page + 1))
- }
- // 是否还有更多
- setTimeout(() => {
- controller.hasMore(this.totalCount() < total /*|| !(data.length < 10)*/)
- }, 800) //处理暂无更多数据视图和列表同时显示出来
- } else {
- if (controller.getStatus() == PullStatus.Refresh) {
- controller.refreshError()
- } else {
- controller.loadError()
- }
- if (page == 1) {
- controller.viewError()
- }
- }
- }
复制代码 SmartDialog弹窗配置
安装
- ohpm install ohos_smart_dialog
复制代码
全局设置一个loadding样式
- OhosSmartDialog({ loadingBuilder: customLoading })
复制代码- /** 自定义页面弹窗 */
- @Builder
- function customLoading(args: ResourceStr = '正在加载中...') {
- Column() {
- Image($r('app.media.loading_refresh')).width(50).height(50)
- Text(args)
- .fontSize(11)
- .fontColor($r('app.color.color_222222'))
- .margin({ top: 11 })
- .maxLines(1)
- .textOverflow({ overflow: TextOverflow.Ellipsis })
- }
- .width(120)
- .height(120)
- .justifyContent(FlexAlign.Center)
- .backgroundColor(Color.White)
- .borderRadius(12)
- }
复制代码
- .onBackPressed(OhosSmartDialog.onBackPressed())
复制代码 以往系列文章
- 《探索 HarmonyOS NEXT(5.0):开启构建模块化项目架构奇幻之旅 —— 模块化基础篇》
- 《探索 HarmonyOS NEXT(5.0):开启构建模块化项目架构奇幻之旅 —— 构建基础特性层》
- 《探索 HarmonyOS NEXT(5.0):开启构建模块化项目架构奇幻之旅 —— 构建公共本领层》
- 《探索 HarmonyOS NEXT(5.0):开启构建模块化项目架构奇幻之旅 —— Tabs底部导航栏》
- 《探索 HarmonyOS NEXT (5.0):开启构建模块化项目架构奇幻之旅 —— 动态路由 ZRouter:引领高效模块通讯的聪明中枢》
若本文对您稍有帮助,诚望您不吝点赞,多谢。
有爱好的同学可以点击查看源码
- gitee:https://gitee.com/jiaojiaoone/explore-harmony-next.git
- github:https://github.com/JasonYinH/ExploreHarmonyNext.git
欢迎加我微信一起交换:+V:yinshiyuba
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |