状态管理与渲染控制

应用级变量的状态管理

Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+

AppStorage

API简介版本
ref如果给定的propName在AppStorage中存在,则返回AppStorage中propName对应属性的引用。否则,返回undefined。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
setAndRef与ref类似,propName存在则返回其引用;不存在则用defaultValue在AppStorage中创建并初始化后返回其引用。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
link与AppStorage中对应的propName建立双向数据绑定,修改会同步回AppStorage并同步到所有绑定该propName的数据和组件。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
setAndLink与link类似,propName存在则返回其双向绑定数据;不存在则用defaultValue创建并初始化后返回其双向绑定数据。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
prop与AppStorage中对应的propName建立单向数据绑定,单向绑定数据的修改不会同步回AppStorage中。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
setAndProp与prop类似,propName存在则返回其单向绑定数据;不存在则用defaultValue创建并初始化后返回其单向绑定数据。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
has判断propName对应的属性是否在AppStorage中存在。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
get获取propName在AppStorage中对应的属性值。如果不存在则返回undefined。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
set在AppStorage中设置propName对应属性的值。仅在propName已存在时生效,不存在时返回false。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
setOrCreatepropName存在且值不同则更新为newValue;不存在则创建propName属性,值为newValue。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
delete在AppStorage中删除propName对应的属性。仅当该属性没有任何订阅者时可删除成功并返回true。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
keys返回AppStorage中所有的属性名。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
clear删除AppStorage中所有属性。仅当AppStorage没有任何订阅者时可删除成功并返回true。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
size返回AppStorage中的属性数量。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
Link与propName建立双向数据绑定。API version 7起支持,10起废弃,建议使用link替代。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
SetAndLink与Link类似,不存在时用defaultValue创建。API version 7起支持,10起废弃,建议使用setAndLink替代。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
Prop与propName建立单向数据绑定,仅支持S类型。API version 7起支持,10起废弃,建议使用prop替代。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
SetAndProp与Prop类似,不存在时用defaultValue创建。API version 7起支持,10起废弃,建议使用setAndProp替代。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
Has判断propName对应的属性是否在AppStorage中存在。API version 7起支持,10起废弃,建议使用has替代。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
Get获取propName在AppStorage中对应的属性值。API version 7起支持,10起废弃,建议使用get替代。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
Set在AppStorage中设置propName对应属性的值。API version 7起支持,10起废弃,建议使用set替代。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
SetOrCreate设置或创建propName对应的属性。API version 7起支持,10起废弃,建议使用setOrCreate替代。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
Delete在AppStorage中删除propName对应的属性。API version 7起支持,10起废弃,建议使用delete替代。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
Keys返回AppStorage中所有的属性名。API version 7起支持,10起废弃,建议使用keys替代。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
staticClear删除AppStorage中所有属性。API version 7起支持,9起废弃,建议使用clear替代。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
Clear删除AppStorage中所有属性,前提是已没有任何订阅者。API version 9起支持,10起废弃,建议使用clear替代。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
IsMutable返回AppStorage中propName对应的属性是否是可变的。API version 7起支持,10起废弃,暂无替代接口。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
Size返回AppStorage中的属性数量。API version 7起支持,10起废弃,建议使用size替代。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+

LocalStorage

API简介版本
constructor创建一个新的LocalStorage实例,使用Object.keys(initializingProperties)返回的属性名及其值初始化实例。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
getShared获取当前Stage共享的LocalStorage实例。API version 10起支持,18起废弃,建议使用UIContext的getSharedLocalStorage替代。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
has判断propName对应的属性是否在LocalStorage中存在。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
get获取propName在LocalStorage中对应的属性值。如果不存在则返回undefined。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
set在LocalStorage中设置propName对应属性的值。仅在propName已存在时生效,不存在时返回false。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
setOrCreatepropName存在且值不同则更新为newValue;不存在则创建propName属性,值为newValue。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
ref如果给定的propName在LocalStorage中存在,则返回其属性的引用。否则,返回undefined。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
setAndRef与ref类似,propName存在则返回其引用;不存在则用defaultValue创建并初始化后返回其引用。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
link与LocalStorage中对应的propName建立双向数据绑定,修改会同步回LocalStorage并同步到所有绑定该propName的数据和组件。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
setAndLink与link类似,propName存在则返回其双向绑定数据;不存在则用defaultValue创建并初始化后返回其双向绑定数据。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
prop与LocalStorage中对应的propName建立单向数据绑定,单向绑定数据的修改不会同步回LocalStorage中。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
setAndProp与prop类似,propName存在则返回其单向绑定数据;不存在则用defaultValue创建并初始化后返回其单向绑定数据。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
delete在LocalStorage中删除propName对应的属性。仅当该属性没有任何订阅者时可删除成功并返回true。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
keys返回LocalStorage中所有的属性名。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
size返回LocalStorage中的属性数量。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
clear删除LocalStorage中所有的属性。仅当属性没有任何订阅者时可删除成功并返回true。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
GetShared获取当前Stage共享的LocalStorage实例。API version 9起支持,10起废弃,建议使用UIContext的getSharedLocalStorage替代。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+

AbstractProperty

API简介版本
get读取AppStorage/LocalStorage中所引用属性的数据。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
set更新AppStorage/LocalStorage中所引用属性的数据,newValue必须是T类型,可以为null或undefined。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
info读取AppStorage/LocalStorage中所引用属性的属性名。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+

SubscribedAbstractProperty

API简介版本
get读取AppStorage/LocalStorage中所同步属性的数据。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
set设置AppStorage/LocalStorage中所同步属性的数据,从API version 12开始可以为null或undefined。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
aboutToBeDeleted取消实例对AppStorage/LocalStorage的单向或双向同步关系,并无效化该实例。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
info返回AppStorage/LocalStorage中所同步属性的属性名。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+

PersistPropsOptions

API简介版本
key要持久化的属性名。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
defaultValue在PersistentStorage和AppStorage中未查询到时,则使用默认值进行初始化。API version 12起可以为null或undefined。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+

PersistentStorage

API简介版本
persistProp将AppStorage中key对应的属性持久化到文件中。该接口通常在访问AppStorage之前调用。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
deleteProppersistProp的逆向操作。将key对应的属性从PersistentStorage中删除,后续AppStorage的操作不再影响持久化。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
persistProps行为与persistProp类似,不同在于可以一次性持久化多个数据,适合在应用启动时初始化。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
keys返回所有持久化属性的属性名的数组。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
PersistProp将AppStorage中key对应的属性持久化到文件中。API version 7起支持,10起废弃,建议使用persistProp替代。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
DeletePropPersistProp的逆向操作。API version 7起支持,10起废弃,建议使用deleteProp替代。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
PersistProps可一次性持久化多个数据。API version 7起支持,10起废弃,建议使用persistProps替代。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
Keys返回所有持久化属性的属性名的数组。API version 7起支持,10起废弃,建议使用keys替代。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+

EnvPropsOptions

API简介版本
key环境变量名称,支持的范围详见内置环境变量说明。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
defaultValue查询不到环境变量key,则使用defaultValue作为默认值存入AppStorage中。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+

Environment

API简介版本
envProp将Environment的内置环境变量key存入AppStorage中。AppStorage中已有对应key则返回false。建议在应用启动时调用。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
envProps和envProp功能类似,不同点在于参数为数组,可以一次性初始化多个数据。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
keys返回环境变量的属性key的数组。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
EnvProp将Environment的内置环境变量key存入AppStorage中。API version 7起支持,10起废弃,建议使用envProp替代。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
EnvProps参数为数组,可一次性初始化多个数据。API version 7起支持,10起废弃,建议使用envProps替代。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
Keys返回环境变量的属性key的数组。API version 7起支持,10起废弃,建议使用keys替代。Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+

内置环境变量说明

Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+

ColorMode

系统当前深浅色模式。

名称说明
LIGHT0浅色模式。
DARK1深色模式。

LayoutDirection

系统的布局方向类型。

名称说明
LTR0从左向右布局。
RTL1从右向左布局。
Auto2自动布局,跟随系统。(API version 8+)

循环渲染

名称说明
ForEachForEach接口基于数组类型数据进行循环渲染,可基于数组数据快速生成结构相同、内容不同的子组件,适用于动态列表、批量数据展示等场景,需与容器组件配合使用Phone12+
LazyForEachLazyForEach是一种懒加载渲染控制组件,从提供的数据源中按需迭代数据并创建相应组件。在大量子组件的场景下,LazyForEach与缓存列表项、动态预加载、组件复用等方法配合使用,可以进一步提升滑动帧率并降低应用内存占用。最佳实践请参考优化长列表加载慢丢帧问题。Phone12+
RepeatRepeat基于数组类型数据来进行循环渲染,一般与滚动容器组件配合使用。Phone12+

ForEach

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

首批接口从 API version 7 开始支持;卡片能力 API 9+,元服务 API 11+。需与容器组件配合使用,返回的组件必须是父容器允许的子组件(如 ListItem 要求父容器为 List 或 ListItemGroup)。初始化渲染时会加载数据源全部数据并创建全部子组件,数据项较多(数百项以上)时建议改用 LazyForEach。

参数类型必填说明
arrArray<any>数据源。设置为undefined时接口不生效;可为空数组(不创建子组件);可传返回数组的函数(如arr.slice(1,3)),但不应使用splice/sort/reverse等改变原数组的函数。
itemGenerator(item: any, index: number) => void组件生成函数,为每个数据项创建对应组件。item为数据项、index为索引(均可选)。建议item类型与arr类型一致,否则可能渲染异常甚至崩溃。函数内不应改变组件状态,可包含if/else条件渲染。
keyGenerator(item: any, index: number) => string键值生成函数,为每个数据项生成唯一且稳定的键值。缺省时默认为(item, index) => index + '__' + JSON.stringify(item)。键值不唯一或不持久可能导致组件复用错误或渲染异常。

属性:支持拖拽排序

LazyForEach

LazyForEach(dataSource: IDataSource, itemGenerator, keyGenerator?, options?: LazyForEachOptions)

首批接口从 API version 7 开始支持,元服务 API 11+;options 参数从 API version 26.0.0 开始支持,仅 Stage 模型可用。在滚动容器中使用时,框架按可视区域按需创建组件,组件滑出可视区域后销毁回收以降低内存占用。属性支持拖拽排序

参数类型必填说明
dataSourceIDataSource数据源,需要开发者实现相关接口。
itemGenerator(item: any, index: number) => void子组件生成函数。函数体必须使用大括号;每次迭代只能且必须生成一个子组件;可用if语句,但每个分支必须创建相同类型的子组件。
keyGenerator(item: any, index: number) => string键值生成函数。缺省时为(item, index) => viewId + '-' + index,仅受index影响。键值需唯一且一致,否则组件复用/更新异常。
optionsLazyForEachOptions配置自定义组件冻结、内存优化策略、资源释放策略。使用时必须设置键值生成函数,否则编译失败。默认冻结AUTO、释放BATCH、内存DEFAULT。

IDataSource

API简介版本
totalCount获得数据总数,由数据源决定实际大小。Phone12+
getData获取索引值index对应的数据,取值范围[0, 数据源长度-1]。应避免在该函数中执行耗时操作。Phone12+
registerDataChangeListener注册数据改变的监听器。Phone12+
unregisterDataChangeListener注销数据改变的监听器。Phone12+

DataChangeListener

API简介版本
onDataReloaded通知组件重新加载所有数据。Phone12+
onDataAdd通知组件index位置有数据添加。API 8+Phone12+
onDataMove通知组件数据从from位置移动到to位置。API 8+Phone12+
onDataDelete通知组件删除index位置的数据。API 8+Phone12+
onDataChange通知组件index位置的数据有变化。API 8+Phone12+
onDatasetChange通知组件一组数据操作(增删改移换重载)。API 12+Phone12+
onDataAdded通知组件index位置有数据添加。已废弃,建议使用onDataAdd替代。Phone12+
onDataMoved通知组件数据移动。已废弃,建议使用onDataMove替代。Phone12+
onDataDeleted通知组件删除index位置的数据。已废弃,建议使用onDataDelete替代。Phone12+
onDataChanged通知组件index位置数据有变化。已废弃,建议使用onDataChange替代。Phone12+

数据操作类型(API 12+)

名称说明
DataOperation数据操作联合类型:DataAddOperation | DataDeleteOperation | DataChangeOperation | DataMoveOperation | DataExchangeOperation | DataReloadOperation。
DataAddOperation添加数据操作。
DataDeleteOperation删除数据操作。
DataChangeOperation改变数据操作。
DataMoveOperation移动数据操作。
DataExchangeOperation交换数据操作。
DataReloadOperation重载所有数据操作。含RELOAD时其余操作全部失效,框架自行调用keyGenerator比对键值。
MoveIndexfrom:起始移动位置;to:目标移动位置。取值范围[0, 数据源长度-1],超出则渲染异常。
ExchangeIndexstart / end:两个交换位置。取值范围[0, 数据源长度-1],超出则渲染异常。
ExchangeKeystart / end:为两个交换位置分配新键值,默认使用原键值。

DataOperationType(API 12+)

名称说明
ADDadd数据添加。
DELETEdelete数据删除。
CHANGEchange数据改变。
MOVEmove数据移动。
EXCHANGEexchange数据交换。
RELOADreload全部数据重载。

LazyForEachOptions(26.0.0+)

名称类型可选说明
customComponentFreezeModeLazyForEachCustomComponentFreezeMode是否使能自定义组件冻结,仅在LazyForEach下直接使用自定义组件时生效。默认AUTO。
releaseStrategyLazyForEachReleaseStrategy资源释放策略。默认BATCH,批量释放节点。
memoryOptimizationStrategyLazyForEachMemOptStrategy内存优化策略,创建时设定,不支持动态修改。默认DEFAULT。
枚举名称说明
LazyForEachCustomComponentFreezeModeAUTO0跟随module.json5配置文件中metadata的设置。
DISABLED1不使能自定义组件冻结。
ENABLED2使能自定义组件冻结。
LazyForEachReleaseStrategyBATCH0默认策略,当前帧释放所有废弃节点,复用率最高;节点层级深、子组件多时可能产生超大帧。
PROGRESSIVE1按当前帧剩余时间逐个释放,帧时间不足则延后,避免超大帧;但LazyForEach会继续持有节点,复用率可能下降、内存升高。
LazyForEachMemOptStrategyDEFAULT0无内存优化策略。
ENABLE_AUTO_CACHE_OPTIMIZATION1 << 0自动内存优化。退后台、组件不可见、整机低内存时释放预加载区域节点(>6G设备保留每侧不超过2个,≤6G设备全部释放);恢复前台/显示/滑动时恢复节点,释放与恢复会触发自定义组件生命周期。

Repeat

Repeat<T>(arr: Array<T>);API 18+ 起数据源支持 RepeatArray<T>

首批接口从 API version 12 开始支持,仅可在 Stage 模型下使用。属性除支持拖拽排序外,还支持下列链式属性。以下属性均不支持在 attributeModifier 中调用。

API简介版本
each组件生成函数,必须设置,否则运行时报错。当所有template的type与templateId返回值都不匹配时用each处理数据项;each也为空则不渲染子组件。参数为RepeatItem,请勿拆开使用。Phone12+
key键值生成函数。Repeat通过对比新旧键值判断数据项的新增、删除、修改,决定组件的复用与更新。Phone12+
virtualScroll开启虚拟滚动,适用于数据项超出可见区域的长列表。开启后仅加载可见区域及预加载区域的子组件。Phone12+
template按template type渲染对应的子组件,适用于列表中存在多种类型数据项、需按类型展示不同样式布局的场景。Phone12+
templateId为当前数据项分配template type,需与template配合使用,返回值应与template的type匹配。Phone12+

类型说明

名称说明
RepeatArray<T>API 18+。数据源参数联合类型:Array<T> | ReadonlyArray<T> | Readonly<Array<T>>,后两者为只读数组,不允许数组对象变更。
RepeatItem<T>item:arr中每一个数据项,T由开发者传入;index:当前数据项对应的索引。
RepeatItemBuilder<T>(repeatItem: RepeatItem<T>) => void,组件生成函数类型。
TemplateTypedFunc<T>(item: T, index: number) => string,返回当前数据项生成的template type。
TemplateOptionscachedCount:当前template缓存池中可缓存子组件节点的最大数量,取值[0, +∞),默认为显示区域与预加载区域节点数之和(只增不减)。推荐设为显示区域节点数,不建议小于2。

VirtualScrollOptions

名称类型可选说明
totalCountnumber期望加载的数据项总数,可不等于数据源长度。与onTotalCount最多设一个,同设时忽略totalCount;缺省或超范围时取数据源长度。=0不加载数据;≤数据源长度时只渲染[0, totalCount-1];>数据源长度时需应用在临近末尾时请求后续数据,建议配合onLazyLoading。
reusablebooleanAPI 18+。是否开启复用功能,默认true。子组件为@ReusableV2装饰的自定义组件时,Repeat自身复用优先,若想用@ReusableV2的复用能力建议关闭。
memoryOptimizationStrategyRepeatMemOptStrategy26.0.0+。内存优化策略,创建时设定,不支持动态修改。默认DEFAULT。
onTotalCount() => numberAPI 19+。自定义计算期望加载的数据项总数,处理规则与totalCount一致;返回非自然数时由数据源长度取代。
onLazyLoading(index: number) => voidAPI 19+。懒加载指定索引的数据。需以arr[index] = ...写入,不允许其他数组操作或写入其他索引;执行后该index仍无数据将导致后续组件无法加载;应避免阻塞式耗时操作。

RepeatMemOptStrategy

名称说明
DEFAULT0无内存优化策略。
ENABLE_AUTO_CACHE_OPTIMIZATION1 << 0自动内存优化。退后台、组件不可见、整机低内存时释放缓存池内所有节点;恢复前台或恢复显示时恢复缓存池节点,释放与恢复会触发自定义组件生命周期。

三者应用范围差异比较

维度ForEachLazyForEachRepeat
起始版本API 7+API 7+API 12+(仅Stage模型)
数据源Array<any>,直接传数组IDataSource,需自行实现接口并手动通知变更Array<T> / RepeatArray<T>(18+),直接传数组,泛型强类型
加载方式全量加载,一次性创建所有子组件懒加载,按可视区域+预加载区域按需创建,滑出即销毁默认全量;调用virtualScroll后按可视区域懒加载
数据变更通知数据源为状态变量时框架自动diff需手动调用DataChangeListener(onDataAdd/Delete/Change/Move/onDatasetChange等)数据源为状态变量时自动更新,无需实现监听器
键值keyGenerator可选,默认index+JSON.stringify(item)keyGenerator可选,默认viewId+index(仅受index影响,易出复用问题,强烈建议自定义).key()可选,配合虚拟滚动时建议提供
节点复用无组件复用,更新时按键值重建按键值复用+组件销毁回收,可配合@Reusable内置模板级缓存池复用(reusable默认开启),可配合@ReusableV2
多类型子组件itemGenerator内用if/else,各分支需为同类型itemGenerator内可用if,每个分支须创建相同类型子组件原生支持.template()+.templateId()多模板,按类型分池复用
容器要求需与容器组件配合,子组件类型受父容器限制同ForEach;懒加载效果需在滚动容器中才体现一般与滚动容器配合;virtualScroll需在滚动容器中使用
数据总数控制由IDataSource.totalCount决定totalCount / onTotalCount可大于数据源长度,配合onLazyLoading实现精准懒加载
内存优化配置LazyForEachOptions:组件冻结、释放策略BATCH/PROGRESSIVE、内存优化策略(26.0.0+)VirtualScrollOptions.memoryOptimizationStrategy、template的cachedCount(26.0.0+)
典型场景数据量小(几十项以内)、结构固定的静态列表、Grid、Tabs等批量展示大数据量长列表、需要精细控制数据变更通知的场景、旧工程既有实现新工程长列表首选:强类型、多模板、复用与懒加载配置更完善、无需手写数据源
不适用/注意数百项以上首屏卡顿、内存占用高需自行维护数据源与监听器,代码量大,键值缺省易导致渲染异常仅Stage模型;each必须设置;属性不能在attributeModifier中调用

备注:Stage 场景下 Repeat 能替代 LazyForEach 吗?

不能完全替代,但绝大多数新写的长列表场景可以。官方指南原话:“相较于 LazyForEach,Repeat 用法更加简单,渲染性能更好,建议开发者优先使用 Repeat。” 同时列了若干硬性限制,下面这些是替代不了的地方。

硬性拦路条件

  1. 状态管理版本。Repeat 的懒加载模式(.virtualScroll())只支持状态管理 V2,与 V1 配合会导致渲染异常。存量工程如果还是 @State/@Observed/@ObjectLink,要么先迁 V2,要么继续用 LazyForEach。这是最常见的阻塞点。
  2. 容器范围。Repeat 懒加载只支持 List、ListItemGroup、Grid、Swiper、WaterFlow 五种容器;不在这个列表里的滚动场景用不了懒加载(关掉 virtualScroll 就退化成全量加载,失去意义)。
  3. 同容器混排。滚动容器内只能包含一个 Repeat,不建议同时有 ListItem、ForEach、LazyForEach,也不建议多个 Repeat。而 LazyForEach 可以和固定 ListItem 混排、多个并存——比如"头部固定项 + 懒加载列表 + 尾部加载更多"这种结构,用 Repeat 需要重构布局。
  4. API 版本。Repeat 从 API 12 起,reusable 18+、onTotalCount/onLazyLoading 19+。要兼容 API 11 及更低只能用 LazyForEach。

架构性差异

IDataSource 是接口,数据不必驻留内存——getData(index) 可以现查数据库或缓存,框架只问 totalCount()。Repeat 必须传真实数组,onLazyLoading(19+)只是允许在读到空洞时往 arr[index] 补写,数组本身仍要承载全部数据。数据量极大或数据不宜全量进内存时,LazyForEach 的模型更合适。

迁移时的坑

  • Repeat 子组件复用不触发 aboutToReuse/aboutToRecycle。依赖这两个回调重绑数据的既有代码搬过去会静默失效。
  • 数组被 Object.seal()/Object.freeze(),或经 makeObserved 转换(某些实现会自动密封)后,Repeat 部分功能失效——它依赖对数组属性的动态修改。
  • .each() 必须提供,否则运行时报错;each/key/template 等属性不能在 attributeModifier 中调用。

结论:新工程、V2 状态管理、容器在那五种之内 → 用 Repeat,复用和多模板能力是净收益。存量 V1 工程、需要容器内混排、目标 API < 12、或数据源不落地成数组 → 保留 LazyForEach。

状态管理V1装饰器

@Consume:与后代组件双向同步:具体开发参考官网链接

  • Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
  • @Provide和@Consume配套使用,用于状态管理V1,实现跨组件层级的双向同步,适用于需要在多层嵌套组件间共享状态的场景,能够避免逐层传递的繁琐,简化组件间的通信逻辑。@Consume装饰的变量作为数据消费方,通过别名或变量名与@Provide装饰的变量建立双向绑定关系。当@Provide或@Consume装饰的变量发生变化时,变化会自动同步到对方。匹配规则:优先使用别名匹配,若未设置别名则使用变量名匹配。

@Link:父子双向同步:具体开发参考官网链接

  • Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
  • @Link用于状态管理V1,接收父组件传入的状态变量的引用,建立父子组件间的双向数据绑定。适用于需要在子组件中直接修改父组件状态、简化父子组件通信的场景。

@LocalStorageLink:LocalStorage双向数据同步:具体开发参考官网链接

  • Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
  • @LocalStorageLink在状态管理V1中使用,用于与LocalStorage中指定键名对应的属性建立双向数据同步:@LocalStorageLink装饰的变量与LocalStorage中对应属性任一方发生变化时,变更均会同步到另一方。适用于需要在多个组件间共享UI状态并与LocalStorage保持数据实时同步的场景,可避免逐层传递数据,保证跨组件数据一致性。

@LocalStorageProp:LocalStorage单向数据同步:具体开发参考官网链接

  • Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
  • @LocalStorageProp在状态管理V1中使用,用于与LocalStorage中指定键名对应的属性建立单向数据同步:LocalStorage中对应属性值的变更会同步到@LocalStorageProp装饰的变量,但仅修改@LocalStorageProp装饰的变量不会同步回LocalStorage。适用于需要在多个组件间共享LocalStorage且仅保持单向数据流的场景,可避免不必要的数据回写。

@ObjectLink:嵌套类对象属性变化:具体开发参考官网链接

  • Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
  • @ObjectLink用于状态管理V1中,接收@Observed装饰的类的实例,并与父组件中的数据源建立双向数据绑定,适用于在子组件中独立观察并监听嵌套类属性并触发UI刷新的场景。

@Observed:嵌套类对象属性变化:具体开发参考官网链接

  • Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
  • @Observed是类装饰器,用于状态管理V1中,观察嵌套类对象的属性变化。

@Prop:父子单向同步:具体开发参考官网链接

  • Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
  • @Prop用于状态管理V1,接收外部传入值,并与父组件建立单向同步关系。当父组件中@State等装饰的状态变量发生变化时,会同步更新到子组件中对应的@Prop变量,触发子组件重新渲染。@Prop采用单向数据流机制,子组件对@Prop变量的修改仅在子组件内部生效,不会反向同步到父组件。适用于子组件需要响应父组件状态变化但不需要反向修改的场景。

@Provide:与后代组件双向同步:具体开发参考官网链接

  • Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
  • @Provide和@Consume配套使用,用于状态管理V1,实现跨组件层级的双向同步,适用于需要跨越多层组件传递状态、避免逐层传递的场景,能够解决组件层级较深时状态传递繁琐的问题。@Provide装饰的变量作为数据源,通过别名或变量名与@Consume装饰的变量建立双向绑定关系。当@Provide或@Consume装饰的变量发生变化时,变化会自动同步到对方。

@State:组件内状态:具体开发参考官网链接

  • Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
  • @State用于状态管理V1,将自定义组件内的普通变量转变为状态变量,当状态变量变化时,触发组件内UI重新渲染。适用于需要在组件内管理可变状态的场景。

@StorageLink:AppStorage双向数据同步:具体开发参考官网链接

  • Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
  • @StorageLink是状态管理V1的装饰器,用于与AppStorage中指定键名的属性建立双向数据同步:当@StorageLink装饰的变量发生变化时,变更会同步到AppStorage中该键名对应的属性;当AppStorage中该键名对应的属性发生变化时,变更也会同步回@StorageLink装饰的变量。适用于需要跨页面、跨Ability共享AppStorage全局状态并与AppStorage保持双向数据同步的场景,可避免逐层传递状态数据,保证数据一致性。

@StorageProp:AppStorage单向数据同步:具体开发参考官网链接

  • Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
  • @StorageProp用于状态管理V1中,与AppStorage中对应的属性建立单向数据同步。AppStorage中对应属性的变化会同步到@StorageProp装饰的变量,但仅修改@StorageProp装饰的变量不会同步回AppStorage。适用于需要跨页面、跨Ability感知AppStorage全局状态变化且仅保持单向数据流的场景,可避免不必要的数据回写。

@Track:class对象属性级更新:具体开发参考官网链接

  • Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
  • @Track用于状态管理V1中,通过装饰class对象的指定属性实现属性级精准观测。当被@Track装饰的属性发生变化时,系统仅更新依赖该属性的UI组件,从而减少不必要的UI重渲染。适用于class对象包含较多属性,需要减少冗余UI刷新、优化渲染性能的场景。

@Watch:状态变量更改通知:具体开发参考官网链接

  • Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
  • @Watch装饰器用于状态管理V1中,监听状态变量的变化,并在变量变化时触发指定回调函数。适用于状态变量变化时需要自动执行联动逻辑、数据同步或计算衍生值的场景。

状态管理V2装饰器

@Computed:计算属性:具体开发参考官网链接

  • Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
  • @Computed为方法装饰器,用于状态管理V2中,装饰getter方法,使其变为计算属性,其返回值会被缓存,仅当依赖的源数据发生变化时才重新计算,减少重复计算带来的开销。

@Consumer:跨组件层级双向同步:具体开发参考官网链接

  • Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
  • @Provider和@Consumer搭配使用,用于状态管理V2中,实现跨组件层级的数据双向同步。@Consumer装饰数据消费方,从数据源获取数据,适用于多层嵌套组件间需要共享和同步状态的场景,可避免通过多层组件逐级传递数据的繁琐操作,简化跨组件层级状态管理。如果@Consumer在组件树中未找到别名匹配的@Provider,将使用自身初始值,不进行数据同步。

@Event:规范组件输出:具体开发参考官网链接

  • Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
  • @Event装饰回调方法,用于状态管理V2中,作为自定义组件的输出。@Event通常与@Param配合使用,@Param负责由父组件向子组件传递数据,@Event负责定义子组件向父组件传递消息的回调接口,适用于需要在子组件中触发父组件状态变更或事件处理的场景。

@Local:组件内部状态:具体开发参考官网链接

  • Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
  • @Local用于状态管理V2中,表示组件内部的状态,使得自定义组件内部的变量具有观测能力。适用于需要在自定义组件内部维护和观测局部状态的场景(如计数器、开关状态等)。使用@Local可以简化组件内部状态管理逻辑,当状态变化时自动触发UI刷新,无需手动管理。

@Monitor:状态变量修改监听:具体开发参考官网链接

  • Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
  • @Monitor装饰器在状态管理V2中用于监听状态变量修改,使得状态变量支持深度监听。适用于需要在状态变量或其嵌套属性发生变化时执行自定义逻辑(如数据同步、UI刷新、日志记录等)的场景。相比状态管理V1的@Watch,@Monitor支持深度监听嵌套对象属性的变化,并从API版本26.0.0开始支持通配符能力,可更灵活地匹配状态变量路径。

@ObservedV2:类属性变化观测:具体开发参考官网链接

  • Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
  • @ObservedV2是类装饰器,用于状态管理V2中。@ObservedV2与@Trace配套使用,装饰类以及类中的属性,使得被装饰的类和属性具有深度观测的能力。相较于状态管理V1的@Observed,@ObservedV2提供了更细粒度的属性级深度观测能力,适用于需要精确追踪嵌套对象属性变化并驱动UI更新的场景,能够有效提升状态管理的性能和灵活性。

@Once:初始化同步一次:具体开发参考官网链接

  • Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
  • @Once作为辅助装饰器,用于状态管理V2中,需要搭配@Param使用,适用于仅从外部初始化一次且不接受后续同步变化的场景。若未与@Param配合使用,@Once单独使用将编译报错。

@Param:组件外部输入:具体开发参考官网链接

  • Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
  • @Param在状态管理V2中用于接收外部输入,实现父子组件之间的单向数据同步。适用于父组件需要向子组件单向传递状态数据的场景,能够简化组件间通信,保证数据流向清晰。@Param装饰的变量不允许在组件内部直接修改,如需子组件向父组件同步数据,请配合@Event使用。

@Provider:跨组件层级双向同步:具体开发参考官网链接

  • Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
  • @Provider和@Consumer搭配使用,用于状态管理V2中,实现跨组件层级的数据双向同步。@Provider装饰数据提供方,为子组件提供数据,适用于组件层级较深、需要跨多层组件共享状态且避免逐层传递数据的场景,可简化状态管理流程,降低组件间的耦合度。

@SyncMonitor:状态变量修改同步监听:具体开发参考官网链接

  • 从API version 23开始支持该装饰器
  • @SyncMonitor用于状态管理V2,同步监听状态变量修改,使得状态变量支持深度监听。适用于需要精确监听对象嵌套属性变化、数组元素修改等深层状态变化的场景,解决了传统监听方式无法感知深层属性变化的问题,提升状态管理的精确性和开发效率。

@Trace:类属性变化观测:具体开发参考官网链接

  • Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
  • @Trace是属性装饰器,用于状态管理V2中。@ObservedV2与@Trace配套使用,装饰类以及类中的属性,使被装饰的类和属性具有深度观测能力,即能够深度观测嵌套对象中属性值的变化,并触发UI自动刷新,适用于需要精确观测和管理类属性变化状态的场景。

@Type:标记类属性的类型:具体开发参考官网链接

  • Phone12+,PC/2in113+,Tablet12+,TV19+,Wearable18+
  • @Type装饰类属性,用于状态管理V2,确保序列化类时不丢失属性的复杂类型。在使用PersistenceV2等持久化能力对复杂类对象进行序列化和反序列化时,类的属性类型信息可能会丢失。通过@Type标记属性的原始类型,可确保在序列化过程中正确保留和还原属性的复杂类型信息,适用于需要持久化或序列化复杂对象的场景,例如应用状态持久化存储、跨组件复杂数据传递等。
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐