HarmonyOS鸿蒙Next中Refresh+List渲染异常
HarmonyOS鸿蒙Next中Refresh+List渲染异常 功能很简单, 下拉刷新时候刷新接口, 发现刷新完以后ui 列表变成了倒序, 但是数据和日志都是正常的啊, 鸿蒙渲染失效了?还是我的装饰器有问题?希望有大佬指点下
刷新前

下拉刷新后,并且点击了第一条数据

两次调用数据的日志

下拉刷新的代码
Refresh({ refreshing: $$this.isRefreshing }) {
List({ scroller: this.scroller }) {
Repeat<MsgConversationItem>(this.msgViewModel.msgConversationItem)
.each((reItem) => {
ListItem() {
this.setItemInfo(reItem.item)
}.width('100%')
.onClick(() => {
Toast.showToast("点击了:" + reItem.index + "-----姓名:" + reItem.item.otherNickname)
})
})
}
.width('100%')
.listDirection(Axis.Vertical)
.alignListItem(ListItemAlign.Center)
.scrollBar(BarState.Off)
.divider({
strokeWidth: 1,
color: $r('app.color.sys_gray_color'),
startMargin: 10,
endMargin: 10
})
}
.layoutWeight(1)
.onRefreshing(() => {
setTimeout(() => {
this.isRefreshing = false;
}, 2000)
this.msgViewModel.getConversationList();
})
装饰器代码
@ObservedV2
export class MsgViewModel extends BaseVM<BaseState> {
private service: MsgService = new MsgService();
@Trace msgConversationItem: Array<MsgConversationItem> = []
public constructor() {
super(new BaseState());
}
getConversationList() {
this.service.getConversationList((msgdata) => {
this.msgConversationItem = Array.from(msgdata.rows!)
for (let i = 0; i < this.msgConversationItem.length; i++) {
Logger.error(TAG, "indx" + i + "----" + this.msgConversationItem[i].otherNickname)
}
});
}
public sendEvent(callback: () => void) {
}
}
从现象上看好像是数据没问题, 就是渲染出现错乱或者有没有类似安卓list的notifychange()方法?
更多关于HarmonyOS鸿蒙Next中Refresh+List渲染异常的实战教程也可以访问 https://www.itying.com/category-93-b0.html
应该是没有设置键值生成函数.key造成的:
Repeat<MsgConversationItem>(this.msgViewModel.msgConversationItem)
.each((reItem) => {
ListItem() {
this.setItemInfo(reItem.item)
}.width('100%')
.onClick(() => {
Toast.showToast("点击了:" + reItem.index + "-----姓名:" + reItem.item.otherNickname)
})
})
.key(reItem => reItem.id)
更多关于HarmonyOS鸿蒙Next中Refresh+List渲染异常的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
总的来说,HarmonyOS是一款非常优秀的操作系统,期待它能在未来带给我们更多惊喜!
那你点击的时候数据是正确的吗,比如我点第一个是王丽雅,我第二张图片还点第一个是谁?,
点击的顺序和日志打出的顺序一致, 只有ui显示是倒序的, 每刷一次ui就倒序一次, 但是从日志看拿的数据是没问题的,
在HarmonyOS Next中,Refresh与List组件结合使用时,渲染异常通常由数据源更新与UI刷新不同步导致。检查Refresh组件的refreshing状态是否在数据加载完成后正确重置。确保List的数据源更新操作在UI主线程执行,避免异步回调中直接修改数据引发布局错乱。可尝试使用状态管理或@State装饰器同步数据状态。
根据你提供的代码和现象,问题很可能出在 ArkTS UI 框架的列表渲染机制 上,特别是 @ObservedV2 装饰的数组被整体替换时,Repeat 渲染可能出现异常。
核心问题分析:
-
数据与 UI 绑定失效:你的
msgConversationItem数组使用@Trace装饰,并在getConversationList()中通过this.msgConversationItem = Array.from(msgdata.rows!)整体替换了数组。虽然数据顺序在日志中正确,但Repeat组件可能无法正确识别数组项的变化,导致渲染顺序错乱。 -
Repeat的key缺失:Repeat渲染动态列表时,如果列表项缺少唯一标识符(key),框架在数组被整体替换后可能无法高效复用现有组件,从而引发渲染顺序问题。
解决方案:
方案一:为 Repeat 添加 key(推荐)
在 Repeat 中指定每个列表项的唯一标识符(如 id),帮助框架正确跟踪和复用组件:
Repeat<MsgConversationItem>(this.msgViewModel.msgConversationItem)
.each((reItem) => {
ListItem() {
this.setItemInfo(reItem.item)
}
.key(reItem.item.id) // 假设列表项有唯一 id 字段
.width('100%')
.onClick(() => {
Toast.showToast("点击了:" + reItem.index + "-----姓名:" + reItem.item.otherNickname)
})
})
方案二:避免数组整体替换 改为修改原数组内容(如清空后追加新数据),而非直接赋值新数组:
getConversationList() {
this.service.getConversationList((msgdata) => {
// 清空原数组
this.msgConversationItem.length = 0;
// 追加新数据
this.msgConversationItem.push(...Array.from(msgdata.rows!));
for (let i = 0; i < this.msgConversationItem.length; i++) {
Logger.error(TAG, "indx" + i + "----" + this.msgConversationItem[i].otherNickname)
}
});
}
方案三:使用 @Observed 装饰数组项
如果 MsgConversationItem 是类,可将其用 @Observed 装饰,并在 Repeat 中直接绑定:
@ObservedV2
export class MsgViewModel extends BaseVM<BaseState> {
@Trace msgConversationItem: Array<MsgConversationItem> = []
// ...
}
// MsgConversationItem 类
@Observed
export class MsgConversationItem {
// 属性定义
}
总结:
优先采用 方案一(添加 key),这是解决列表渲染顺序问题的标准做法。如果问题依旧,可结合方案二(避免整体替换数组)。方案三适用于复杂数据结构场景。


