HarmonyOS 鸿蒙Next `LazyForEach`和`Reusable`在数据源index:0处依次新增多个元素的问题
HarmonyOS 鸿蒙Next LazyForEach
和Reusable
在数据源index:0处依次新增多个元素的问题
大佬们,我根据组件复用官方示例里的代码,改了一下,因为我需要在数据源的index:0处新增元素,并会在复用的子组件内触发一个回调方法执行父组件中的方法,见如下关键代码:
父组件:
// 数据源index:0处新增元素、通知数据源listener新增、通知数据源listener重载
Button('列表index:0处新增').onClick(() => {
let uuid = util.generateRandomUUID().substring(0,7)
// 忽略ColorModel里的构造参数,这里表示unshift了一个对象并reload数据源,unshift里已经通知数据源listener新增了。
this.colorData.unshift(new ColorModel(uuid, uuid, Color.Black))
this.colorData.dataReload()
})
// this.colorData已经实现了IDataSource接口
LazyForEach(this.colorData, (colorModel: ColorModel, index: number) => {
ListItem() {
OneMomentNoModifier({
colorModel,
index,
action: () => {
// 在点击Button新增超过1个元素之后,父组件打印的就是错的了,怀疑是复用组件的问题
hilog.info(0x0000, TAG, `#parent#action(): id[${colorModel.id}], index[${index}]`);
}
})
}
}, (color: ColorModel, index: number) => `${color.id}_${index}`)
子组件:
@Reusable
@Component
export struct OneMomentNoModifier {
@Prop colorModel: ColorModel
@Prop index: number
action?: () => void
build() {
Column() {
// 子组件显示的始终是对的
Text(this.colorModel.id + '/' +this.index)
}
.onclick(() => {
if (undefined !== this.action) {
hilog.info(0x0000, TAG, `#child#action(): id[${this.colorModel.id}], index[${this.index}]`);
this.action()
}
})
}
发现同时使用LazyForEach
和Reusable
之后,通知数据源在index:0处新增数据,this.notifyDataAdd(0)
并reload数据源,超过1条之后,父组件在执行子组件回调的时候使用colorModel
对象里的数据就是不对的了。
我现在的解决办法是在子组件的action
回调内,将colorModel
以参数形式传出来,因为子组件通过@Prop
得到的对象始终是对的:
子组件
// 子组件
this.action(this.colorModel)
// 父组件
action: (obj: ColorModel) => {
// 使用obj
}
这样虽然问题解决了,但是父组件中使用colorModel
时,用的colorModel
是从父里的LazyForEach赋值 -> 子通过回调传参 -> 父接收回调参数
得来的,总觉得不对劲,想请问大家发生这样的问题是因为什么?我现在怀疑是复用组件的问题,但又不知道怎么解决…(在index:0处新增一个,意味着复用了刚刚列表底部被顶下去消失不见被回收的组件,被回收的组件内的action
还是第一次渲染时候的箭头函数?并没有被重新赋值吗?但是子组件内的action
又不能加@Prop
注解,会报错…)
这里是输出的日志:
新增第一个时是对的,应该是List
的cachedCount
设置的5,屏幕显示条数 + 5正好 >= 总条目10。所以应该是每次新增数据的时候,父组件回调里的colorModel
就是错的。
更多关于HarmonyOS 鸿蒙Next `LazyForEach`和`Reusable`在数据源index:0处依次新增多个元素的问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
每次新增ColorModel时,LazyForEach里所有子节点的索引都变动了,所有子节点都需要重新渲染,因为子组件标记了@Reusable,所以旧的节点没有被销毁,放入复用缓存中,会在下一次新增时被复用。复用时父组件action不会重新渲染,所以父组件都是旧的参数。
[@Reusable](/user/Reusable)
@Component
export struct OneMomentNoModifier {
@Prop colorModel: ColorModel
@Prop index: number
action?: () => void
uid: string = ''
index2: number = 0
build() {
Column() {
Text(this.uid + '/' + this.index2)
}
.width('80%')
.height('8%')
.onClick(() => {
})
.backgroundColor(this.colorModel.color)
.margin({ top: 10 })
}
}
在子组件打断点,新增渲染时可以看出,每次新增都都会渲染2次子组件。渲染效果
次数 | 当前显示 | 缓存池 |
---|---|---|
1 | +a0 | |
2 | a1,+b0 | a0 |
3 | a2,b1+a0 | a1,b0 |
4 | a3,b2+a1,b0 | a2,b1,a0 |
5 | a4,b3+a2,b1,a0 | a3,b2,a1,b0 |
6 | a5,b4+a3,b2,a1,b0 | a4,b3,a2,b1,a0 |
从缓存池中获取已缓存的子组件,子组件不够时新渲染组件,同时把当前的所有节点放入缓存池中。因为总是重复从缓存池中获取组件,所以参数始终是a和b
更多关于HarmonyOS 鸿蒙Next `LazyForEach`和`Reusable`在数据源index:0处依次新增多个元素的问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
也就是说我现在除了现有的解决办法,只有不用复用组件才可以实现这个父组件action
里正确的效果了嘛?