欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 产业 > ForEach刷新UI机制

ForEach刷新UI机制

2025/2/26 18:41:11 来源:https://blog.csdn.net/xingxing_yan/article/details/143832842  浏览:    关键词:ForEach刷新UI机制

官网地址:ForEach

在ArkUI中,提供了ForEach循环语句,用来初始化一个列表数据,我们知道,当ForEach中的数组发生变化时,会引起UI的刷新,但是究竟如何变化,会引起UI怎样的刷新,还需要进一步的去探索其逻辑。

1. ForEach参数和规则

参数:

参数名

类型

必填

说明

arr

Array<Object>

数据源,为Array类型的数组。

说明:

- 可以设置为空数组,此时不会创建子组件。

- 可以设置返回值为数组类型的函数,例如arr.slice(1, 3),但设置的函数不应改变包括数组本身在内的任何状态变量,例如不应使用Array.splice(),Array.sort()或Array.reverse()这些会改变原数组的函数。

itemGenerator

(item: Object, index: number) => void

组件生成函数。

- 为数组中的每个元素创建对应的组件。

- item参数:arr数组中的数据项。

- index参数(可选):arr数组中的数据项索引。

说明:

- 组件的类型必须是ForEach的父容器所允许的。例如,ListItem组件要求ForEach的父容器组件必须为List组件。

keyGenerator

(item: Object, index: number) => string

键值生成函数。

- 为数据源arr的每个数组项生成唯一且持久的键值。函数返回值为开发者自定义的键值生成规则。

- item参数:arr数组中的数据项。

- index参数(可选):arr数组中的数据项索引。

说明:

- 如果函数缺省,框架默认的键值生成函数为(item: T, index: number) => { return index + '__' + JSON.stringify(item); }

- 键值生成函数不应改变任何组件状态。

键值的生成规则和itemGenerator 、keyGenerator有关:

1.如果是keyGenerator这个函数缺省,此时生成规则由框架确定,生成规则为item和index拼接,(item: any, index: number)=>{ return index +“_”+ JSON.stringify(item); }。

2.如果keyGenerator没有缺省且未包含index,当itemGenerator中包含index,生成的规则是自定义键值与index拼接成的字符串,如(item)=>item+2 对应的键值是 index+'_'+(item+2),如果itemGenerator中未包含index,此时keyGenerator的生成规则是由开发者自定义的键值生成规则。

3.如果keyGenerator没有缺省,且包含index,此时不管itemGenerator中是否包含index,生成的键值规则都是开发者自定义的键值生成规格,框架不会对去拼接index。

2. 场景和示例

ForEach在初始化时,会加载数组中所有的数据,并为其创建控件,也就是厨师数组如果有n项,就会创建n个对象

@Component
export struct ForEachView {@State private list: number[] = [1, 2, 3]private list1: number[] = [1, 2]private list2: number[] = [1, 2, 3, 4, 5]private isOne: boolean = true;build() {Column({ space: 20 }) {Column({ space: 10 }) {ForEach(this.list, (item: number) => {Child({ item: item })}, (item: number, index: number) => {console.debug(`ForEach: item = ${item}, index = ${index}`)return item.toString()})}Row({ space: 10 }) {Button("add").onClick(() => {this.list.push(4)})Button("insert").onClick(() => {this.list.splice(1, 0, 5)})Button("delete").onClick(() => {this.list.pop();})Button("changeArray").onClick(() => {if (this.isOne) {this.list = this.list1} else {this.list = this.list2}this.isOne = !this.isOne;})}}}
}@Component
struct Child {@Prop item: number;aboutToAppear(): void {console.debug(`aboutToAppear: child${this.item}`)}build() {Text(this.item.toString()).width(100).height(50).border({ width: 2, color: Color.Red })}aboutToDisappear(): void {console.debug(`aboutToDisappear: child${this.item}`)}}

2.1. 场景一:初始化

运行结果:

初始化时,list中有三个元素,ForEach遍历所有元素,并创建了三个Child控件

2.2. 场景二:数组增加元素

运行结果:

可以看出,增加了Item 4后,ForEach循环还是遍历的四遍,但是此时只有child4执行了aboutToAppear的方法。这是因为ForEach的keyGenerator设置唯一的key值,ForEach刷新时,发现如果相同的key值的控件如果已经存在,就不会重新创建。

2.3. 场景三:数组插入元素

运行结果:

插入和增加一样,ForEach也会全部遍历,但是只创建了不存在的child5

2.4. 场景四:删除

运行结果:

ForEach遍历剩余的元素,并将删除的元素下树,调用child3的aboutToDisapper的方法

2.5. 场景五:更换数组对象

  1. 将数组list1赋值list, 元素数量减少

运行结果:

由于list1和list之间有部分项的重合,所以,list1赋值给list后,重复的部分之前已经存在,不创建,list1没有的部分则进行了删除

  1. 将list2赋值给list,元素数量增加

运行结果:

ForEach对所有元素遍历,对不存在的元素进行创建

  1. 赋值完全不同的list3

运行结果:

ForEach遍历数组所有元素,将原来的元素全部移除,然后创建新的元素。

3. 总结

对于ForEach而言,只要数组发生了变化, 无论是长度变化还是重新赋值, ForEach都回重新遍历一遍。但是ForEach会根据keyGenerator的值判断是否需要重新创建控件,所以keyGenerator是非常关键的参数,建议自己定义一个生成规则,不要用系统默认的。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词