ArkTS-ArkUI-ForEach:循环渲染

一.官方文档

ForEach的官方文档!

二.基本语法

ForEach(arr: Array,                                   //要遍历的数组

itemGenerator: (item: any, index: number) => {

                                                        //页面组件生成函数

},

keyGenerator?: (item: any, index: number) =>{

                        //键生产函数,为数组每一项生成唯一标识,是组件是否重新渲染的判断标准

}

)

arr:数组
itemGenerator:组件生成的回调函数,循环渲染组件  
   
(item: any, index: number) =>{ 需要循环渲染的组件 } -- item:数组遍历出来的元素,index:元素下标
  
  
itemGenerator:键值生成的回调函数。用于给循环生成的组件绑定一个唯一且固定的键值  
   
(item: any, index: number) =>{ 写循环生成键值逻辑 } -- item:数组遍历出来的元素,index:元素下标    

ForEach接口基于数组类型数据来进行对组件的循环渲染,需要与容器组件配合使用,且接口返回的组件应当是允许包含在ForEach父容器组件中的子组件。

来看看文档吧:

参数名

参数类型

必填

参数描述

arr

Array<any>

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

说明

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

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

itemGenerator

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

组件生成函数。

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

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

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

说明

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

keyGenerator

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

键值生成函数。

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

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

说明

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

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

 文档内容比较多,我们来简单总结一下:

先创建一个数组就比如叫titles,然后用foreach(this.来引用titles,(item:类型,index:number)=>{})
item和index即参数变量名,可以换成别的,a啊,b呀无所谓

item代表遍历时数组中的元素,index代表数组下标

类型要与数组元素类型一致,类型可省,但建议写上方便后期引用。

keyGenerator 通常可省略,系统会有个默认生成值为:index + '_' + JSON.stringify(item)

自己写的话要注意确保每个数组元素生成的结果要不一样,有然相同项只会生成一个UI组件;而且要确保新加入的项不会和原有项生成相同结果,不然UI刷新会受影响,因为只有key变化时UI才刷新。

 来渲染个小数组练练手吧:

 原格式里item是参数变量,可取任何合规名字,类型是 any,即 arr 可以是任意类型的数组。这里的a只是给item换个名而已,所以这里a代表遍历时数组 III 中三个数组元素,因为是循环渲染,ForEach生成三次。

接下来实现实例吧:

三.实现ForEach循环渲染

最终页面:

1.分析页面

还记得要构建一个页面的第一步吗?

分析

 1.1商品从上至下排列——》确定布局Column

 1.2标题文字,选择嵌套一个Row布局

 1.3商品布局

可以发现商品的布局都是相同的,左侧图片右侧两行文字。那我们就可以实现一个然后使用循环渲染来实现。

图片与文字是在一行中——》嵌套Row容器

右侧文字竖直排列——》嵌套Column容器

 2.实现一个商品

2.1嵌套Row容器设置图片

.padding(10) 设置容器内部边距

2.2再次嵌套Column容器

 添加属性,使其置于交叉轴开始端。

一个商品的效果就实现了,接下来只要使用ForEach循环渲染来实现即可。 

3.ForEach实现

首先创建一个类和数组来存放商品信息。

使用this.来引用Item数组,再为组件生成函数添加类型。

最后再将显示的固定量改变为变量,即从数组中获取。

这样就达到了预期效果:

Watch Fit 3 现补贴50元,更新商品列表: 

 

分析变更:页面无较大变化,Fit 3右侧Column容器中两个文本变为四个。但依旧使用ForEach循环渲染,需要对是否有补贴进行判断。若补贴不为0,则使用新布局。

在Item类在新增变量discount作为补贴价,且初值设置为0,若后期未设discount则默认为0。

 在循环渲染中使用if...else语句进行判断选择相应布局。

更新后:

 

最终代码: 

class Item{
  name:string
  image:ResourceStr
  price:number
  discount:number

  constructor(name:string,image:ResourceStr,price:number,discount:number=0) {
    this.name=name
    this.image=image
    this.price=price
    this.discount=discount
  }
}

@Entry
@Component

struct Index {
  private items:Item[]=[   //Item类型 (Array<Item>)
    new Item('WATCH FIT 3',$r('app.media.watchfit3'),999,50),
    new Item('Pura 70',$r('app.media.pura70'),6999),
    new Item('Mate X5',$r('app.media.mateX5'),11999),
    new Item('Matepad 11.5S',$r('app.media.matePad'),2299),
    new Item('MateBook XPro',$r('app.media.mateBookXPro'),19999),
    new Item('FreeBuds Lipstick 2',$r('app.media.freeBudslipstick2'),1999)
  ]


  build() {
      Column({space:4}) {
        Row(){
          Text('商品列表')
            .fontSize(30)
            .fontStyle(FontStyle.Italic)
            .fontWeight(FontWeight.Bold)
        }
        .width('100%')
        ForEach(
          this.items,
          (item:Item)=>{    //:Item(类型)可不写,若不写下方无法直接弹出其can'shu
            Row({space:10}){
              Image(item.image)
                .width(100)
              Column({space:4}){
                if(item.discount) {
                  Text(item.name)
                    .fontWeight(FontWeight.Bold)
                    .fontSize(20)
                  Text('¥'+item.price)
                    .fontSize(15)
                    .fontColor('#CCC')
                    .decoration({type: TextDecorationType.LineThrough})  
                        //文本装饰线样式及其颜色
                  Text('补贴:¥'+item.discount)
                    .fontSize(16)
                    .fontColor(Color.Red)
                  Text('折扣价:¥'+(item.price-item.discount))
                    .fontSize(17)
                    .fontColor(Color.Red)
                } else {
                  Text(item.name)
                    .fontWeight(FontWeight.Bold)
                    .fontSize(20)
                  Text('¥'+item.price)
                    .fontSize(17)
                    .fontColor(Color.Red)

                }

              }
              .height('100%')
              .alignItems(HorizontalAlign.Start)  //交叉轴上对齐方式
            }
            .height(120)      //每一行的行高固定
            .width('100%')
            .backgroundColor(Color.White)
            .borderRadius(20)   //边框圆角
            .padding(10)


          }
        )


      }
      .height('100%')
      .width('100%')
      .backgroundColor('#FFECECEC')
      .padding(20)  //组件内部间距

  }
}

静水深流,生活亦需内敛之美!

  • 24
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值