尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

HarmonyOS 多设备短视频开发 : 14 — 列表 List 与 ForEach 渲染

HarmonyOS 多设备短视频开发 : 14 — 列表 List 与 ForEach 渲染 14 — 列表 List 与 ForEach 渲染一、引言短视频应用的信息形态几乎都是列表视频推荐流是纵向翻页列表评论是纵向滚动列表个人作品是九宫格网格PC 侧边导航是纵向菜单。ArkUI 中这些场景由 List、Grid 配合 ForEach/Repeat 数据循环实现。本文结合multi-short-video项目代码讲解 List/ListItem 的基础用法、ForEach 键值生成规则以及项目采用的 Repeat virtualScroll 复用机制。二、List/ListItem 基础用法List 是纵向或横向滚动的容器子项必须包在 ListItem 中。评论区列表features/multishortvideocomment/src/main/ets/view/Comment.ets的结构是List 作为滚动容器内部通过数据循环生成评论项末尾再追加一个没有更多了的尾项List() { RepeatCommentDataModel(this.commentData) .each((item: RepeatItemCommentDataModel) { ListItem() { Column() { Row() { ...头像、昵称、点赞... } Column() { ...评论内容、时间地点、回复区... } } .width(CommonConstants.FULL_PERCENT) .padding({ top: 8, bottom: 8 }) } }) .key((item: CommentDataModel) JSON.stringify(item)) .virtualScroll({ totalCount: this.commentData.length }) ListItem() { Row() { Text($r(app.string.nothing_more))... } .width(CommonConstants.FULL_PERCENT) .padding({ top: 20, bottom: 30 }) .margin({ bottom: 56 }) .justifyContent(FlexAlign.Center) } } .width(CommonConstants.FULL_PERCENT) .height(CommonConstants.FULL_PERCENT) .scrollBar(BarState.Off) // 关闭滚动条视觉更干净 .padding({ left: 16, right: 16 })scrollBar(BarState.Off)关闭系统滚动条——短视频产品追求沉浸感滚动条通常隐藏。List 默认纵向滚动可通过listDirection改为横向divider属性可统一设置分割线样式但评论项内部自带间距与圆角背景项目选择不用分割线、用padding分隔。三、ForEach 键值生成规则ForEach 的第三个参数是键值生成函数用于标识每个子项、指导框架做差异更新。公共 Tabs 组件common/multishortvideobase/src/main/ets/components/MSVTabs.ets用它生成 TabContentForEach(data, (tabItem: MSVDataModel, index: number) { TabContent() { if (tabItem.content) { MSVTabContent({ content: tabItem.content }) } } .tabBar(this.MSVTabBar(tabItem, index)) .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM]) }, (tabItem: MSVDataModel) JSON.stringify(tabItem.content))键值生成需遵循两个原则一是唯一性相同键值会导致框架复用错误节点造成子项状态错乱二是稳定性键值不应在数据未变化时改变否则框架会认为子项全部变更、重建整个列表。项目用JSON.stringify将对象序列化作为键值适用于对象内字段变化即代表内容变化的场景。四、Repeat 与 virtualScroll列表项复用与内存控制项目列表场景统一使用了 ArkUI 新 APIRepeat替代 ForEach并叠加.virtualScroll()开启虚拟滚动。评论列表、作品网格、视频 Swiper 均如此例如个人作品页features/multishortvideoindividual/src/main/ets/view/Works.etsGrid() { RepeatWorksDataModel(this.worksData) .each((item: RepeatItemWorksDataModel) { GridItem() { Stack({ alignContent: Alignment.BottomStart }) { Image(item.item.pic) .width(100%).height(100%) .objectFit(ImageFit.Cover) Row({ space: 5 }) { MSVTextIcon({ src: $r(app.media.ic_like), iconSize: 16 }) Text(item.item.likes).fontSize($r(sys.float.Body_S))... } .margin({ left: 12, bottom: 12 }) } } .aspectRatio(0.68) .borderRadius(...) .clip(true) }) .key((item: WorksDataModel) JSON.stringify(item)) .virtualScroll({ totalCount: this.worksData.length }) } .columnsTemplate(new WidthBreakpointTypestring(repeat(3,1fr), repeat(4,1fr), repeat(6,1fr), repeat(6,1fr), repeat(2,1fr)).getValue(this.windowInfo.widthBp)) .rowsGap(8) .columnsGap(8) .scrollBar(BarState.Off)virtualScroll让框架只创建视口附近可见的列表项滑出屏幕的子项被回收复用。对于评论这类数万条的潜在场景这是内存控制的关键视频列表中的AdaptiveVideo.ets则在 Swiper 上设置.cachedCount(2)预加载相邻页保证滑动流畅。对比 ForEach 的全量创建Repeat virtualScroll 将渲染复杂度从 O(n) 降到 O(视口项数)。五、视频推荐与作品列表的多端差异同一个Repeat数据源可以服务于不同容器与不同设备。PC 端侧边导航用 List 渲染菜单products/pc/src/main/ets/view/Index.ets手机端推荐流用 Swiper 纵向翻页AdaptiveVideo.ets作品页则根据设备与断点动态切换网格列数——repeat(3,1fr)表示每行 3 列手写板/平板用repeat(4,1fr)电脑用repeat(6,1fr)侧栏展开时压缩为repeat(2,1fr).columnsTemplate(deviceInfo.deviceType tv ? (this.showSideIndividual ? repeat(3,1fr) : repeat(4,1fr)) : new WidthBreakpointTypestring(repeat(3,1fr), repeat(4,1fr), repeat(6,1fr), repeat(6,1fr), repeat(2,1fr)).getValue(this.showSideIndividual ? WindowUtil.getInstance().getCustomWidthBreakpoint(this.individualWidth) : this.windowInfo.widthBp))数据层通过 ViewModel 统一供给WorksViewModel.getWorksList()返回WorksDataModel[]UI 层只负责如何渲染这种数据与视图分离让同一份数据在四种设备上呈现不同形态成为可能。六、总结与最佳实践长列表必开虚拟滚动评论、作品、视频流统一使用Repeat virtualScroll避免大列表卡顿与内存暴涨。键值要唯一且稳定用JSON.stringify(item)做键值时确保对象字段完整反映内容变化。列表尾项单独处理用 List 末尾追加 ListItem 呈现加载中/没有更多比在数据里塞占位对象更干净。隐藏滚动条保沉浸产品追求沉浸时用scrollBar(BarState.Off)再以间距/圆角替代分割线。容器与数据解耦同一数据源可服务 List/Grid/Swiper 多种容器列数与布局交给断点/设备条件决定。
返回列表