接口描述
1 2 3 4 5 |
ForEach( arr: Array, itemGenerator: (item: any, index: number) => void, keyGenerator?: (item: any, index: number) => string ) |
示例
首次渲染
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
@Entry @Component struct Parent { @State simpleList: Array<string> = ['one', 'two', 'three']; build() { Row() { Column() { ForEach(this.simpleList, (item: string) => { ChildItem({ item: item }) }, (item: string) => item) } .width('100%') .height('100%') } .height('100%') .backgroundColor(0xF1F3F5) } } @Component struct ChildItem { @Prop item: string; build() { Text(this.item) .fontSize(50) } } |
数据源存在相同值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
@Entry @Component struct Parent { @State simpleList: Array<string> = ['one', 'two', 'two', 'three']; build() { Row() { Column() { ForEach(this.simpleList, (item: string) => { ChildItem({ item: item }) }, (item: string) => item) } .width('100%') .height('100%') } .height('100%') .backgroundColor(0xF1F3F5) } } @Component struct ChildItem { @Prop item: string; build() { Text(this.item) .fontSize(50) } } |
非首次渲染
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
@Entry @Component struct Parent { @State simpleList: Array<string> = ['one', 'two', 'three']; build() { Row() { Column() { Text('点击修改第3个数组项的值') .fontSize(24) .fontColor(Color.Red) .onClick(() => { this.simpleList[2] = 'new three'; }) ForEach(this.simpleList, (item: string) => { ChildItem({ item: item }) .margin({ top: 20 }) }, (item: string) => item) } .justifyContent(FlexAlign.Center) .width('100%') .height('100%') } .height('100%') .backgroundColor(0xF1F3F5) } } @Component struct ChildItem { @Prop item: string; build() { Text(this.item) .fontSize(30) } } |
骨架屏
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
@Entry @Component struct ArticleList { @State simpleList: Array<number> = [1, 2, 3, 4, 5]; build() { Column() { ForEach(this.simpleList, (item: number) => { ArticleSkeletonView() .margin({ top: 20 }) }, (item: number) => item.toString()) } .padding(20) .width('100%') .height('100%') } } @Builder function textArea(width: number | Resource | string = '100%', height: number | Resource | string = '100%') { Row() .width(width) .height(height) .backgroundColor('#FFF2F3F4') } @Component struct ArticleSkeletonView { build() { Row() { Column() { textArea(80, 80) } .margin({ right: 20 }) Column() { textArea('60%', 20) textArea('50%', 20) } .alignItems(HorizontalAlign.Start) .justifyContent(FlexAlign.SpaceAround) .height('100%') } .padding(20) .borderRadius(12) .backgroundColor('#FFECECEC') .height(120) .width('100%') .justifyContent(FlexAlign.SpaceBetween) } } |
数据源数组项变化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
class Article { id: string; title: string; brief: string; constructor(id: string, title: string, brief: string) { this.id = id; this.title = title; this.brief = brief; } } @Entry @Component struct ArticleListView { @State isListReachEnd: boolean = false; @State articleList: Array<Article> = [ new Article('001', '第1篇文章', '文章简介内容'), new Article('002', '第2篇文章', '文章简介内容'), new Article('003', '第3篇文章', '文章简介内容'), new Article('004', '第4篇文章', '文章简介内容'), new Article('005', '第5篇文章', '文章简介内容'), new Article('006', '第6篇文章', '文章简介内容') ] loadMoreArticles() { this.articleList.push(new Article('007', '加载的新文章', '文章简介内容')); } build() { Column({ space: 5 }) { List() { ForEach(this.articleList, (item: Article) => { ListItem() { ArticleCard({ article: item }) .margin({ top: 20 }) } }, (item: Article) => item.id) } .onReachEnd(() => { this.isListReachEnd = true; }) .parallelGesture( PanGesture({ direction: PanDirection.Up, distance: 80 }) .onActionStart(() => { if (this.isListReachEnd) { this.loadMoreArticles(); this.isListReachEnd = false; } }) ) .padding(20) .scrollBar(BarState.Off) } .width('100%') .height('100%') .backgroundColor(0xF1F3F5) } } @Component struct ArticleCard { @Prop article: Article; build() { Row() { Image($r('app.media.icon')) .width(80) .height(80) .margin({ right: 20 }) Column() { Text(this.article.title) .fontSize(20) .margin({ bottom: 8 }) Text(this.article.brief) .fontSize(16) .fontColor(Color.Gray) .margin({ bottom: 8 }) } .alignItems(HorizontalAlign.Start) .width('80%') .height('100%') } .padding(20) .borderRadius(12) .backgroundColor('#FFECECEC') .height(120) .width('100%') .justifyContent(FlexAlign.SpaceBetween) } } |
数据源数组项子属性变化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
@Observed class Article { id: string; title: string; brief: string; isLiked: boolean; likesCount: number; constructor(id: string, title: string, brief: string, isLiked: boolean, likesCount: number) { this.id = id; this.title = title; this.brief = brief; this.isLiked = isLiked; this.likesCount = likesCount; } } @Entry @Component struct ArticleListView { @State articleList: Array<Article> = [ new Article('001', '第0篇文章', '文章简介内容', false, 100), new Article('002', '第1篇文章', '文章简介内容', false, 100), new Article('003', '第2篇文章', '文章简介内容', false, 100), new Article('004', '第4篇文章', '文章简介内容', false, 100), new Article('005', '第5篇文章', '文章简介内容', false, 100), new Article('006', '第6篇文章', '文章简介内容', false, 100), ]; build() { List() { ForEach(this.articleList, (item: Article) => { ListItem() { ArticleCard({ article: item }) .margin({ top: 20 }) } }, (item: Article) => item.id) } .padding(20) .scrollBar(BarState.Off) .backgroundColor(0xF1F3F5) } } @Component struct ArticleCard { @ObjectLink article: Article; handleLiked() { this.article.isLiked = !this.article.isLiked; this.article.likesCount = this.article.isLiked ? this.article.likesCount + 1 : this.article.likesCount - 1; } build() { Row() { Image($r('app.media.icon')) .width(80) .height(80) .margin({ right: 20 }) Column() { Text(this.article.title) .fontSize(20) .margin({ bottom: 8 }) Text(this.article.brief) .fontSize(16) .fontColor(Color.Gray) .margin({ bottom: 8 }) Row() { Image(this.article.isLiked ? $r('app.media.iconLiked') : $r('app.media.iconUnLiked')) .width(24) .height(24) .margin({ right: 8 }) Text(this.article.likesCount.toString()) .fontSize(16) } .onClick(() => this.handleLiked()) .justifyContent(FlexAlign.Center) } .alignItems(HorizontalAlign.Start) .width('80%') .height('100%') } .padding(20) .borderRadius(12) .backgroundColor('#FFECECEC') .height(120) .width('100%') .justifyContent(FlexAlign.SpaceBetween) } } |
拖拽排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
@Entry @Component struct ForEachSort { @State arr: Array<string> = []; build() { Row() { List() { ForEach(this.arr, (item: string) => { ListItem() { Text(item.toString()) .fontSize(16) .textAlign(TextAlign.Center) .size({height: 100, width: "100%"}) }.margin(10) .borderRadius(10) .backgroundColor("#FFFFFFFF") }, (item: string) => item) .onMove((from:number, to:number) => { let tmp = this.arr.splice(from, 1); this.arr.splice(to, 0, tmp[0]) }) } .width('100%') .height('100%') .backgroundColor("#FFDCDCDC") } } aboutToAppear(): void { for (let i = 0; i < 100; i++) { this.arr.push(i.toString()) } } } |
文档地址
https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-rendering-control-foreach-V5