HarmonyOS应用开发实战:半天实现知乎日报项目(八、知乎日报详情页的实现)
在本篇博文中,我们将探讨如何使用 HarmonyOS Next 框架开发一个知乎日报的详情页,逐步介绍所用到的组件及代码实现。知乎日报是个小巧完整的小项目,这是一个循序渐进的过程,适合初学者和有一定开发经验的工程师参考。
1. 项目背景
知乎日报是一个非常热门的新闻聚合应用,通过API接口获取最新的新闻内容。在我们的实现中,我们将从知乎接口获取详情数据,并在应用中展示相应的内容。
1.1 知乎接口介绍
知乎日报提供了api接口,方便个人开发者联手使用。接口介绍:
获取最新日报
get https://news-at.zhihu.com/api/4/news/latest
历史日报
get https://news-at.zhihu.com/api/4/news/before/20240617
热门日报
get http://news-at.zhihu.com/api/4/news/hot
主题日报
get http://news-at.zhihu.com/api/4/news/theme/2024
2016年
get http://news-at.zhihu.com/api/4/news/before/20240721
日报详情
get http://news-at.zhihu.com/api/4/news/9773253
1.2日报详情页特殊处理
需要特别注意的是,知乎日报的详情页需要特殊处理,因为,因为后台返回的竟然是html.是的,你没听错,这有点儿。。。,但也不麻烦。我自己造了个后台接口特殊处理过了,处理为了这个样子:
2. 主要组件介绍
2.1 DetailPageBuilder
这是构建整个详情页的入口,是NavDestination组件包括着的一个子页面,它使用了HarmonyOS提供的Navigation组件路由,通过主页的点击进入详情页。
    //zhihu.ets (主页)
    build() {
        Navigation(this.pageStack){
            Column({ space: 0 }) {
              // 内容项
              Swiper(this.swiperController) {
                LazyForEach(this.swiperData, (item: ZhiNewsItem) => {
                  Stack({ alignContent: Alignment.Center }) {
                    Image(item.image)
                      .width('100%')
                      .height(200)
                      .backgroundColor(0xAFEEEE)
                      .zIndex(1)
                      .onClick(() => {
                        //this.pageStack.pushPathByName("PageOne", item)
                        //点击跳转到详情页
                        this.pageStack.pushDestinationByName("ZhiPageDetail", { id:item.id }).catch((e:Error)=>{
                          // 跳转失败,会返回错误码及错误信息
                          console.log(`catch exception: ${JSON.stringify(e)}`)
                        }).then(()=>{
                          // 跳转成功
                        });
                      })
                    // 显示轮播图标题
2.2 DetailPage
该结构体是页面的核心包含所有的状态管理和生命周期回调。我们在其中定义了一些主要的状态变量,例如消息、页面数据和页面ID等。
2.3 生命周期回调
- aboutToAppear: 组件即将出现时的处理逻辑,可以在这里做初始化操作。
- aboutToDisappear: 组件即将消失时的处理逻辑,通常用于清理操作。
3. 代码实现
以下是主要代码部分:
    import { getZhiHuDetail } from '../../../common/api/zhihu';
    import { BaseResponse, ErrorResp, ZhiDetailRespData, ZhiDetailItem } from '../../../common/bean/ApiTypes';
    import { Log } from '../../../utils/logutil';
    import { LengthMetrics } from '@kit.ArkUI';
    @Builder
    export function DetailPageBuilder() {
      DetailPage();
    }
    @Component
    struct DetailPage {
      @State message: string = 'Hello World';
      pageStack: NavPathStack = new NavPathStack();
      private pathInfo: NavPathInfo | null = null;
      @State detailData: ZhiDetailRespData | null = null;
      private pageId = '';
      // 组件生命周期
      aboutToAppear() {
        Log.info('Detail aboutToAppear');
      }
      // 组件生命周期
      aboutToDisappear() {
        Log.info('Detail aboutToDisappear');
      }
      build() {
        NavDestination() {
          Scroll() {
            Column({ space: 0 }) {
              Stack({ alignContent: Alignment.Bottom }) {
                Image(this.detailData?.image).width('100%').height(250).zIndex(1);
                
                // 显示轮播图标题
                Text(this.detailData?.title)
                  .padding(5)
                  .margin({ bottom: 10 })
                  .width('100%')
                  .height(50)
                  .textAlign(TextAlign.Center)
                  .maxLines(2)
                  .textOverflow({ overflow: TextOverflow.Clip })
                  .fontSize(16)
                  .fontColor(Color.White)
                  .opacity(100)
                  .backgroundColor('#808080AA')
                  .zIndex(2);
              }.height(250); // 设置高度
              Text(`${this.detailData?.author ?? ""} ${this.detailData?.bio ?? ""}`)
                .fontSize(14)
                .fontColor("#999")
                .padding(10).width('100%');
              Column() {
                ForEach(this.detailData?.content, (item: ZhiDetailItem, idx) => {
                  if (item.types === 'p') {
                    Text(item.value).fontSize(16).padding(10).lineSpacing(LengthMetrics.px(30)).width('100%').alignSelf(ItemAlign.Start);
                  } else if (item.types === 'p.strong') {
                    Text(item.value).fontSize(16).fontWeight(FontWeight.Bold).padding(10).width('100%').alignSelf(ItemAlign.Start);
                  } else if (item.types === 'img') {
                    Image(item.value).padding(10);
                  }
                });
              }
            }
          }
        }
        .title("日报详情")
        .width('100%')
        .height('100%')
        .onReady(ctx => {
          this.pageStack = ctx.pathStack;
          this.pathInfo = ctx.pathInfo;
          interface params {
            id: string;
          }
          let par = ctx.pathInfo.param as params;
          Log.debug("par:%s", par.id);
          this.pageId = par.id;
          Log.info('current page config info is ' + JSON.stringify(ctx.getConfigInRouteMap()));
        })
        .onShown(() => {
          console.info('Detail onShown');
          getZhiHuDetail(this.pageId).then((res) => {
            Log.debug(res.data.message);
            Log.debug("request", "res.data.code:%{public}d", res.data.code);
            this.detailData = res.data;
          }).catch((err: BaseResponse<ErrorResp>) => {
            Log.debug("request", "err.data.code:%d", err.data.code);
            Log.debug("request", err.data.message);
          });
        });
      }
    }
4. 代码解析
- 数据获取:使用getZhiHuDetail(this.pageId)获取当前页面的内容,并将数据存储在detailData状态中。
- 组件渲染:通过NavDestination和Scroll组件容纳整个页面,确保内容在可滚动视图内。
- 动态数据展示:使用${this.detailData?.author ?? ""} ${this.detailData?.bio ?? ""}实现了数据的安全合并,确保了在获取到的数据不存在时不发生错误。
- 生命周期:在NavDestination的onReady事件里拿到上个页面传递的参数值,在onShown事件里完成数据请求,拿到详情数据。
5. 结论
通过本篇博文,我们对如何使用 HarmonyOS Next 开发知乎日报详情页进行了深入的探讨。这不仅涵盖了从API获取数据到页面渲染的整个流程,还详细介绍了相关组件的使用方法。在实践中,开发者可以根据具体需求进一步扩展和优化页面功能。
希望这篇博文对你理解 HarmonyOS Next 项目开发有所帮助!如果你有任何问题,欢迎在下方留言讨论。
项目开源地址
zhihudaily: HarmonyOS NEXT 项目开发实战,仿知乎日报的实现
作者:猫哥 (blog.csdn.net/qq8864),转载请注明出处。
团队:坚果派 团队介绍:坚果派由坚果等人创建,团队拥有12个华为HDE带领热爱HarmonyOS/OpenHarmony的开发者,以及若干其他领域的三十余位万粉博主运营。专注于分享HarmonyOS/OpenHarmony、ArkUI-X、元服务、仓颉。团队成员聚集在北京,上海,南京,深圳,广州,宁夏等地,目前已开发鸿蒙原生应用,三方库60+,欢迎交流。
写在最后
最后,推荐下笔者的业余开源app影视项目“爱影家”,推荐分享给与我一样喜欢免费观影的朋友。【注】:该项目仅限于学习研究使用!请勿用于其他用途!
开源地址: 爱影家app开源项目介绍及源码
https://gitee.com/yyz116/imovie
编辑
- 4回答
- 7粉丝
- 5关注
- HarmonyOS应用开发实战:半天实现知乎日报项目(九、知乎日报项目接口使用指南)
- HarmonyOS应用开发实战:半天实现知乎日报项目(四、仿知乎日报的首页轮播图实现)
- HarmonyOS应用开发实战,半天实现知乎日报项目(二、网络接口的封装使用)
- HarmonyOS应用开发实战:半天实现知乎日报项目(六、首页轮播图的完整实现)
- HarmonyOS应用开发实战:半天实现知乎日报项目(三、ArkUI页面底部导航TabBar的实现)
- HarmonyOS应用开发实战:半天实现知乎日报项目(七、知乎日报List列表下拉刷新及上滑加载更多分页的实现)
- HarmonyOS 应用开发实战:半天实现知乎日报完整项目(一、开篇,环境准备)
- HarmonyOS应用开发实战:半天实现知乎日报项目( 五、组件导航Navigation使用详解)
- 鸿蒙开发(八):公司详情页面的实现
- HarmonyOS NEXT应用开发边学边玩系列:从零实现一影视APP (五、电影详情页的设计实现)
- [HarmonyOS NEXT 实战案例:电商应用] 基础篇 - 垂直分割布局打造商品详情页
- [HarmonyOS NEXT 实战案例:电商应用] 基础篇 - 垂直分割布局打造商品详情页
- 《仿盒马》app开发技术分享-- 商品详情页(10)
- 《仿盒马》app开发技术分享-- 订单详情页(32)
- 《仿盒马》app开发技术分享-- 回收订单详情页(46)

