【HarmonyOS实战开发】鸿蒙NEXT 渲染控制

33 篇文章 0 订阅
33 篇文章 0 订阅

目录

●渲染控制概述
●if/else:条件渲染
●ForEac:循环渲染
●LazyForEach:数据懒加载
●Repeat:循环渲染(推荐)
●ConnentSlot:混合开发

渲染控制概述

ArkUI通过自定义组件的build()函数和@builder装饰器声明式UI描述语句构建相应的的UI。在声明式描述语句中开发者除了使用系统组件外,还可以使用渲染语句来辅助UI的构建,这些渲染控制语句包括控制组件是否显示的条件语句,基于数组数据快速生成组件的虚幻渲染语句,针对大数据量的数据懒加载语句,针对混合模式开发的组件渲染语句。

if/else:条件渲染

ArkTS提供了渲染控制的能力,条件渲染可根据应用的不同状态,使用if、else和else if渲染对应状态下的UI内容。

使用规则

●支持if、else和else if语句
●if、else后跟随的条件语句可以使用状态变量
●允许在容器组件内使用,通过条件渲染语句构建不同的子组件。
●条件渲染语句在涉及到组件的父子关系时是"透明"的,当父组件和子组件之间存在一个或多个if语句时,必须遵守父组件关于子组件使用的规则
●每个分支内部的构建海曙必须遵循构建函数的规则,并创建一个或多个组件。无法创建组建的空构建函数会产生语法错误
●某些容器组件限制子组件的类型或数量,将条件渲染语句用于这些组件内时,这些限制同样应用于条件渲染语句内创建的组件。例如:Grid容器组件的子组件仅支持GridItem组件,在Grid内使用条件渲染语句时,条件渲染语句内仅允许使用GridItem组件。

更新机制

当if、else后跟随的状态判断中使用的状态变量值变化时,条件渲染语句会进行更新,更新步骤如下:

1.评估if和else if的状态判断条件,如果分支没有变化,无需执行以下步骤。如果分支有变化,则执行2、3步骤
2.删除此前构建的所有子组件
3.执行新分支的构造函数,将获取到的组件添加到if父容器中。如果缺少适用的else分支,则不构建然和内容。条件可以包括Typescript表达式。对于构造函数中的表达式,此类表达式不得更改应用程序状态。

ForEach:循环渲染

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

接口 描述

ForEach(
  arr: Array,
  itemGenerator: (item: Object, index: number) => void,
  keyGenerator?: (item: Object, index: number) => string
)

以下是参数的详细说明:

在这里插入图片描述

键值生成规则

在ForEach循环渲染过程中,系统会为每个数组元素生成一个唯一且持久的键值,用于表示对应的组件。当这个键值发生变化时,ArkUI框架将视为该数组元素已被替换或修改,并会基于新的键值创建一个新的组件。
ForEach提供了一个名为keyGenerator的参数,这是一个函数,开发者可以通过它自定义键值生成规则。如果开发者没有定义keyGenerator函数,则ArkUI框架会使用默认的键值生成函数。
ArkUI框架对于ForEach的键值生成有一套特定的判断规则,这主要与itemGenerator函数的第二个参数index以及keyGenerator函数的第二个参数index有关,具体的键值生成规则判断逻辑如下图:
在这里插入图片描述

LazyForEach:数据懒加载

LazyForEach从提供的数据源中按需迭代数据,并在每次迭代过程中创建相应的组件。当在滚动容器中使用了LazyForEach,框架会根据滚动容器可视区域按需创建组件,当组件划出可视区域外时,框架会进行组件销毁回收以降低内存占用。

接口描述

LazyForEach(
    dataSource:IDataSource, //需要进行数据迭代的数据源
    itemGenerator:(item:Object,index:number) => void, 
    keyGenerator:(item:Object,index:number) => string
):void

参数:

在这里插入图片描述

IDataSource类型说明

interface IDataSource {
    totalCount():number; //获得数据总数
    getData(index:number):Object; //获取索引值对应的数据
    registerDataChangeListener(listener:DataChangeListener):void; //注册数据改变的监听器
    unregisterDataChangeListener(listener:DataChangeListener):void; //注销数据改变的监听器
}

在这里插入图片描述

DataChangeListener类型说明

interface DataChangeListener {
    onDataReloaded():void; //重新加载数据完成调用
    onDataAdded(index:number):void; //添加数据完成后调用
    onDataMoved(from:number,to:number):void; //数据移动起始位置与数据移动目标位置交换完成后调用
    onDataDeleted(index:number):void; //删除数据完成后调用
    onDataChaged(index:number):void; //改变数据完成后调用
    onDataAdd(index:number):void; //添加数据完成后调用
    onDataMove(from:number,to:number):void; //数据移动起始位置与数据移动目标位置交换完成后调用
    onDataDelete(index:number):void; //删除数据完成后调用
    onDataChange(index:number):void; //改变数据完成后调用
    onDatasetChange(dataOperations:DataOperation[]):void; //批量数据处理后调用
}

DataOperation类型说明

type DataOperation = 
        DataAddOperation      |  //添加数据操作
        DataDeleteOperation   |  //删除数据操作
        DataChangeOperation   |  //改变数据操作
        DataMoveOperation     |  //移动数据操作
        DataExchangeOperation |  //交换数据操作
        DataReloadOperation      //重载所有数据操作

DataAddOperation

interface DataAddOperation {
    type:DataOperationType.ADD,    //数据添加类型
    index:number,                  //插入数据索引值
    count?:number,                 //插入数量,默认值为1
    ket?:string|Array<string>      //为插入的数据分配键值
}

DataDeleteOperation

interface DataDeleteOperation{
    type:DataOperationType.DELETE, //数据删除类型
    index:number,                  //起始删除位置索引值
    count?:number                  //删除数据数量,默认值为1
}

DataChangeOperation

interface DataChangeOperation{
    type:DataOperationType.CHANGE, //数据改变类型
    index:number,                  //改变的数据的索引值
    key?:string                    //为改变的数据分配新的键值,默认使用原键值
}

DataMoveOperation

interface MoveIndex {
    from:number;           //起始移动位置
    to:number;             //目的移动位置
}

interface DataMoveOperation {
    type:DataOperationType.MOVE, //数据移动类型
    index:MoveIndex,
    key?:string                  //为被移动的数据分配新的键值,默认使用原键值
}

DataExchangeOperation

interface ExchangeIndex {
    start:number;                     //第一个交换位置
    end:number;                       //第二个交换位置
}
interface ExchangeKey {
    start:string;                     //为第一个交换的位置分配新的键值,默认使用原键值
    end:string;                       //为第二个交换的位置分配新的键值,默认使用原键值
}
interface DataExchangeOperation {
    type:DataOperationType.EXCHANGE,  //数据交换类型
    index:ExchangeIndex,
    key?:ExchangeKey
}

DataReloadOperation

interface DataReloadOperation {      //当onDataChange含有DataOperationType.RELOAD操作时,其余操作全部失效,框架会自己调用keyGenerator进行键值比对
    type:DataOperationType.RELOAD    //数据全部重新加载
}

使用限制

LazyForEach必须在容器组件内使用,仅有List、Grid、Swiper以及WaterFlow组件支持数据懒加载(可配置cachedCount属性,即只加载可视部分以及其前后少量数据用于缓冲),其他组件仍然是一次性加载所有数据。
LazyForEach在每次迭代中,必须创建且只允许创建一个子组件
生成的子组件必须是允许包含在LazyForEach父容器组件中的子组件
允许LazyForEach包含在if/else条件渲染语句中,也允许LazyForEach中出现if/else条件渲染语句
键值生成器必须针对每个数据生成唯一的值,如果键值相同,将导致键值相同的UI组件渲染出问题
LazyForEach必须使用DataChangeListener对象来进行更新,第一个参数dataSource使用状态变量时,状态变量改变不会触发LazyForEach的UI刷新
为了高性能渲染,通过DataChangeListener对象的onDataChange方法来更新UI时,需要生成不同于原来的键值来触发组件刷新

键值生成规则

在LazyForEach循环渲染过程中,系统会为每个item生成一个唯一且持久的键值,用于标识对应的组件。当这个键值变化时,ArkUI框架将视为该数组元素已被替换或修改,并会基于新的键值创建一个新的组件。
LazyForEach提供了一个名为keyGenerator的参数,这是一个函数,开发者可以通过它自定义键值的生成规则。如果开发者没有定义keyGenerator函数,则ArkUI框架会使用默认的键值生成函数,即(item: Object, index: number) => { return viewId + ‘-’ + index.toString(); }, viewId在编译器转换过程中生成,同一个LazyForEach组件内其viewId是一致的。

Repeat:循环渲染(推荐)

Repeat组件基于数组类型数据进行循环渲染,需要与容器组件配合使用,且接口返回的数组应当是允许包含在Repeat父容器组件中的子组件。
Repeat循环渲染和ForEach相比有两个区别,一是优化了部分更新场景下的渲染性能,二是组件生成函数的索引index由框架侧来维护。

接口描述

Repeat 组件构造

declare const Repeat:<T>(arr:Array<T>) => RepeatAttribute<T>

参数说明:

在这里插入图片描述

Repeat组件属性

declare class RepeatAttribute<T> {
    each(itemGenerator:(repeatItem:RepeatItem<T>) => void) : RepeatAttribute<T>;
    key(keyGenerator:(item:T,index:number) => string) : RepeatAttribute<T>;
}

参数说明:

在这里插入图片描述

RepeatItem 类型

interface RepeatItem<T> {
    item:T,
    index?:number
}

参数说明:
在这里插入图片描述

键值生成规则

在Repeat循环渲染过程中,系统会为每个数组元素生成一个唯一且持久的键值,用于标识对应的组件。当这个键值变化时,ArkUI框架将视为该数组元素已被替换或修改,会基于此去做对应的更新。若当前数组有数据项对应的键值与其他项重复,Repeat会为每一项数据补上index作为新的键值。
Repeat提供了key属性,参数是一个函数,开发者可以通过它自定义键值的生成规则。如果开发者没有调用key属性,则ArkUI框架会使用默认的键值生成函数。
ArkUI框架对于Repeat的键值生成有一套特定的判断规则,具体的键值生成规则判断逻辑如下图所示。

ContentSlot: 混合开发

用于渲染并管理Native层使用C-API创建的组件。
支持混合模式开发,当容器是ArkTS组件,子组件在Native侧创建时,推荐使用ContentSlot占位组件。

接口

ContentSlot组件接口

//当前开发者需要使用ArkUI提供的NodeContent作为管理器
ContentSlot(content:Content)

在这里插入图片描述


abstract class Content {
}

ContentSlotInterface

(content:Content):ContentSlotAttribute;
当内容添加到占位符组件时调用
系统能力: SystemCapability.ArkUI.ArkUI.Full
参数:

ContentSlotAttribute

定义ContentSlot属性,以防止不正确的递归使用ContentSlot
系统能力: SystemCapability.ArkUI.ArkUI.Full

Native侧接口

在这里插入图片描述

写在最后

●如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我两个小忙:
●点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
●关注小编,同时可以期待后续文章ing ,不定期分享原创知识。

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值