概述
Refresh组件支持下拉刷新,包裹list组件,下拉事件中更新列表
这里我们需要提前了解一下 @Builder装饰器 的基本用法
ArkUI提供了一种轻量的UI元素复用机制@Builder,该自定义组件内部UI结构固定,仅与使用方进行数据传递,开发者可以将重复使用的UI元素抽象成一个方法,在build方法里调用。
为了简化语言,我们将@Builder装饰的函数也称为“自定义构建函数”。
具体用法可参考官网文档:文档中心
在后面我们也会去详细的讲解 @Builder装饰器 的使用
对于滚动有List和Scroll,List适合数量不确定的滚动,比如评论列表等;Scroll适合数量确定的滚动
上拉刷新
这里主要用到 Refresh组件 的 onRefreshing 函数
@Entry
@Component
struct Index {// 是否需要刷新@Staterefreshing: boolean = false// 自定义构建函数--给组件传递@BuilderrefreshContent() {// Text('正在玩命加载中...')// .width('100%')// .textAlign(TextAlign.Center)// .backgroundColor(Color.Pink)Row({space: 8}) {LoadingProgress().height(24)Text('正在玩命加载中...')}.width('100%').padding(12).justifyContent(FlexAlign.Center)}// 定义随机数据@Statelist: number[] = Array(20).fill(Date.now())// 下拉加载用到scroller:Scroller = new Scroller()@StateisEnd: boolean = falsebuild() {RelativeContainer() {// Refresh 刷新组件// 参数说明:refreshing 组件当前是否处于刷新中状态;builder 自定义刷新区域显示内容(结构体),参数可选Refresh({refreshing: $$this.refreshing, builder: this.refreshContent}) {List() {ForEach(this.list, (item: number) => {ListItem() {Row() {Text(item.toString()).width('100%').padding(20).border({width: {bottom: 1},style: {bottom: BorderStyle.Dashed},color: Color.Gray})}}})}}// 监听是否刷新完毕(真正的刷新操作)-从而进行数据更新操作.onRefreshing(() => {setTimeout(() => {// 更新数据this.list = Array(20).fill(Date.now())// 手动关闭刷新状态this.refreshing = false}, 1000)})}.width('100%').height('100%')}
}
下拉加载
注册三个事件,开始滚动,滚动结束,滚动至列表尾部(触发两次,滚动至+回弹)
设置变量是否滚动底部,开始滚动false,滚动至列表尾部true,滚动结束判断变量进行数据追加
触底了--只有触底了才会进行数据加载,这里会出现加载两次的情况,因此在这里不适合进行数据的请求操作
对于数据的请求我们需要利用 onScrollStart 和 onScrollStop 和 onReachEnd 三个进行联合判断,从而进行数据请求操作
数据请求逻辑:1.开始滚动,更新状态为没有触底不进行数据加载;2.停止滚动,是否触底了触底了才加载数据,反之不加载数据;3.触底,记录触底了
下拉加载数据完成了应该让滚动条滚动到底部去,不然不知道是否已经加载成功了
import { promptAction } from '@kit.ArkUI'
import HmLoading from './components/HmLoading'@Entry
@Component
struct Index {// 是否需要刷新@Staterefreshing: boolean = false// 自定义构建函数--给组件传递@BuilderrefreshContent() {// Text('正在玩命加载中...')// .width('100%')// .textAlign(TextAlign.Center)// .backgroundColor(Color.Pink)Row({space: 8}) {LoadingProgress().height(24)Text('正在玩命加载中...')}.width('100%').padding(12).justifyContent(FlexAlign.Center)}// 定义随机数据@Statelist: number[] = Array(20).fill(Date.now())// 下拉加载用到:用于下拉加载成功后让滚动条滚动到底部自动scroller:Scroller = new Scroller()@StateisEnd: boolean = false@StateisLoading: boolean = falsetotal:number = 43build() {Stack() {RelativeContainer() {// Refresh 刷新组件// 参数说明:refreshing 组件当前是否处于刷新中状态;builder 自定义刷新区域显示内容(结构体),参数可选Refresh({refreshing: $$this.refreshing, builder: this.refreshContent}) {List({scroller: this.scroller}) {ForEach(this.list, (item: number) => {ListItem() {Row() {Text(item.toString()).width('100%').padding(20).border({width: {bottom: 1},style: {bottom: BorderStyle.Dashed},color: Color.Gray})}}})if(this.list.length > this.total) {ListItem() {Row() {Text('我是有底线的~')}.width('100%').padding(12).justifyContent(FlexAlign.Center)}}}// 开始滚动.onScrollStart(() => {promptAction.showToast({message: '开始滚动'})this.isEnd = false;})// 停止滚动.onScrollStop(() => {// 节流效果if(this.isLoading || this.list.length > this.total) return;promptAction.showToast({message: '停止滚动'})if(this.isEnd) {this.isLoading = true;// 数据加载setTimeout(() => {const list:number[] = Array(10).fill(Math.random())this.list.push(...list)this.scroller.scrollEdge(Edge.Bottom)this.isLoading = false;}, 1000)}})// 触底了--只有触底了才会进行数据加载,这里会出现加载两次的情况,因此在这里不适合进行数据的请求操作// 对于数据的请求我们需要利用 onScrollStart 和 onScrollStop 和 onReachEnd 三个进行联合判断,从而进行数据请求操作// 数据请求逻辑:1.开始滚动,更新状态为没有触底不进行数据加载;2.停止滚动,是否触底了触底了才加载数据,反之不加载数据;3.触底,记录触底了.onReachEnd(() => {promptAction.showToast({message: '触底了'})this.isEnd = true;})}// 监听是否刷新完毕(真正的刷新操作)-从而进行数据更新操作.onRefreshing(() => {setTimeout(() => {// 更新数据this.list = Array(20).fill(Date.now())// 手动关闭刷新状态this.refreshing = false}, 1000)})}.width('100%').height('100%')if(this.isLoading) {Column() {HmLoading()}.height('100%').width('100%').backgroundColor('#ba0a0000').justifyContent(FlexAlign.Center)}}}
}