【鸿蒙开发】新闻列表页面练习

1. 安装依赖包

ohpm install @ohos/axios @ohos/pulltorefresh@2.0.1

2. 页面布局

@Entry
@Component
struct Index {
  build() {
    Column() {
      Row() {
        Image($r("app.media.left"))
          .height(16)
          .position({
            x: 10,
            y: 16
          })
        Text("新闻列表")
          .width("100%")
          .height(50)
          .fontSize(18)
          .textAlign(TextAlign.Center)
      }
      .width("100%")
      .height(50)

      Column() {
        // 新闻列表
      }
      .backgroundColor(Color.Red)
      .width('100%')
      .layoutWeight(1)
    }
    .width("100%")
    .height("100%")
  }
}

3. 上拉加载更多/下拉更新

3.1 引入插件

import { PullToRefresh } from '@ohos/pulltorefresh'
import axios from "@ohos/axios"

3.2 添加新闻数据类型

export interface News {
  name?: string
}

3.3 创建 scroller 控制器

private scroller: Scroller = new Scroller();

3.4 添加新闻列表数据

  @State newsList: News[] = []

3.5 添加组件

        PullToRefresh({
          // 必传项,列表组件所绑定的数据
          data: $newsList,
          // 必传项,需绑定传入主体布局内的列表或宫格组件
          scroller: this.scroller,
          // 必传项,自定义主体布局,内部有列表或宫格组件
          customList: () => {
            this.buildNewsList();
          },
          customLoad: null,
          customRefresh: null
        })

3.6 添加 buildNewsList 方法

  @Builder
  buildNewsList() {
    List({ scroller: this.scroller }) {
      ForEach(this.newsList, (item: News, index: number) => {
        ListItem() {
          Text(`${index + 1} -- ${item.name}`)
            .width("100%")
            .height(100)
            .padding(10)
            .textOverflow({ overflow: TextOverflow.Ellipsis })
            .maxLines(1)
        }
      })
    }
    .divider({
      strokeWidth: 1,
      color: "#ddd"
    })
    .edgeEffect(EdgeEffect.None)
  }

3.7 添加api接口获取新闻数据

  // 分页
  @State page: number = 1
  // 是否还有更多
  @State hasMore: boolean = true

  aboutToAppear() {
    this.fetchNewsData()
  }

  async fetchNewsData(resolve?: (value: string | PromiseLike<string>) => void) {
    if (!this.hasMore) {
      resolve?.('true')
      return
    }
    const apiUrl = 'https://api.thepaper.cn/contentapi/nodeCont/getByChannelId'
    const res = await axios.post(apiUrl, {
      channelId: "119908",
      excludeContIds: [27131749, 27132788, 27142995],
      listRecommendIds: [27142995, 27131749],
      pageNum: this.page,
      pageSize: 10,
      province: null,
      startTime: 1713577612993,
    })
    const result: News[] = res.data.data.list
    this.newsList = this.newsList.concat(result)
    this.page++
    // 判断有没有数据
    if (this.page > 5) {
      this.hasMore = false
    }
    resolve?.('true')
  }

3.8 添加上拉加载方法

          // 可选项,上拉加载更多回调
          onLoadMore: () => {
            return new Promise<string>((resolve) => {
              return this.fetchNewsData(resolve)
            });
          },

 

3.9 添加下拉刷新

          // 可选项,下拉刷新回调
          onRefresh: () => {
            return new Promise<string>((resolve) => {
              this.hasMore = true
              this.page = 1
              this.newsList = []
              return this.fetchNewsData(resolve)
            });
          },

4. 完整代码

import { PullToRefresh } from '@ohos/pulltorefresh'
import axios from "@ohos/axios"

export interface News {
  name?: string
}

@Entry
@Component
struct Index {
  private scroller: Scroller = new Scroller();
  @State newsList: News[] = []
  // 分页
  @State page: number = 1
  // 是否还有更多
  @State hasMore: boolean = true

  aboutToAppear() {
    this.fetchNewsData()
  }

  async fetchNewsData(resolve?: (value: string | PromiseLike<string>) => void) {
    if (!this.hasMore) {
      resolve?.('true')
      return
    }
    const apiUrl = 'https://api.thepaper.cn/contentapi/nodeCont/getByChannelId'
    const res = await axios.post(apiUrl, {
      channelId: "119908",
      excludeContIds: [27131749, 27132788, 27142995],
      listRecommendIds: [27142995, 27131749],
      pageNum: this.page,
      pageSize: 10,
      province: null,
      startTime: 1713577612993,
    })
    const result: News[] = res.data.data.list
    this.newsList = this.newsList.concat(result)
    this.page++
    // 判断有没有数据
    if (this.page > 5) {
      this.hasMore = false
    }
    resolve?.('true')
  }

  @Builder
  buildNewsList() {
    List({ scroller: this.scroller }) {
      ForEach(this.newsList, (item: News, index: number) => {
        ListItem() {
          Text(`${index + 1} -- ${item.name}`)
            .width("100%")
            .height(100)
            .padding(10)
            .textOverflow({ overflow: TextOverflow.Ellipsis })
            .maxLines(1)
        }
      })
    }
    .divider({
      strokeWidth: 1,
      color: "#ddd"
    })
    .edgeEffect(EdgeEffect.None)
  }

  build() {
    Column() {
      Row() {
        Image($r("app.media.left"))
          .height(16)
          .position({
            x: 10,
            y: 16
          })
        Text("新闻列表")
          .width("100%")
          .height(50)
          .fontSize(18)
          .textAlign(TextAlign.Center)
      }
      .width("100%")
      .height(50)

      Column() {
        // 新闻列表
        PullToRefresh({
          // 必传项,列表组件所绑定的数据
          data: $newsList,
          // 必传项,需绑定传入主体布局内的列表或宫格组件
          scroller: this.scroller,
          // 必传项,自定义主体布局,内部有列表或宫格组件
          customList: () => {
            this.buildNewsList();
          },
          // 可选项,下拉刷新回调
          onRefresh: () => {
            return new Promise<string>((resolve) => {
              this.hasMore = true
              this.page = 1
              this.newsList = []
              return this.fetchNewsData(resolve)
            });
          },
          // 可选项,上拉加载更多回调
          onLoadMore: () => {
            return new Promise<string>((resolve) => {
              return this.fetchNewsData(resolve)
            });
          },
          customLoad: null,
          customRefresh: null
        })
      }
      .width('100%')
      .layoutWeight(1)
    }
    .width("100%")
    .height("100%")
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值