鸿蒙(Harmony)状态管理与渲染控制:2026年9月之前的
状态管理与渲染控制
- 应用级变量的状态管理
- 内置环境变量说明
- 循环渲染
- 状态管理V1装饰器
- @Consume:与后代组件双向同步:具体开发参考官网链接
- @Link:父子双向同步:具体开发参考官网链接
- @LocalStorageLink:LocalStorage双向数据同步:具体开发参考官网链接
- @LocalStorageProp:LocalStorage单向数据同步:具体开发参考官网链接
- @ObjectLink:嵌套类对象属性变化:具体开发参考官网链接
- @Observed:嵌套类对象属性变化:具体开发参考官网链接
- @Prop:父子单向同步:具体开发参考官网链接
- @Provide:与后代组件双向同步:具体开发参考官网链接
- @State:组件内状态:具体开发参考官网链接
- @StorageLink:AppStorage双向数据同步:具体开发参考官网链接
- @StorageProp:AppStorage单向数据同步:具体开发参考官网链接
- @Track:class对象属性级更新:具体开发参考官网链接
- @Watch:状态变量更改通知:具体开发参考官网链接
- 状态管理V2装饰器
- @Computed:计算属性:具体开发参考官网链接
- @Consumer:跨组件层级双向同步:具体开发参考官网链接
- @Event:规范组件输出:具体开发参考官网链接
- @Local:组件内部状态:具体开发参考官网链接
- @Monitor:状态变量修改监听:具体开发参考官网链接
- @ObservedV2:类属性变化观测:具体开发参考官网链接
- @Once:初始化同步一次:具体开发参考官网链接
- @Param:组件外部输入:具体开发参考官网链接
- @Provider:跨组件层级双向同步:具体开发参考官网链接
- @SyncMonitor:状态变量修改同步监听:具体开发参考官网链接
- @Trace:类属性变化观测:具体开发参考官网链接
- @Type:标记类属性的类型:具体开发参考官网链接
应用级变量的状态管理
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+ |
| setOrCreate | propName存在且值不同则更新为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+ |
| setOrCreate | propName存在且值不同则更新为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+ |
| deleteProp | persistProp的逆向操作。将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+ |
| DeleteProp | PersistProp的逆向操作。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
系统当前深浅色模式。
| 名称 | 值 | 说明 |
|---|---|---|
| LIGHT | 0 | 浅色模式。 |
| DARK | 1 | 深色模式。 |
LayoutDirection
系统的布局方向类型。
| 名称 | 值 | 说明 |
|---|---|---|
| LTR | 0 | 从左向右布局。 |
| RTL | 1 | 从右向左布局。 |
| Auto | 2 | 自动布局,跟随系统。(API version 8+) |
循环渲染
| 名称 | 值 | 说明 |
|---|---|---|
| ForEach | ForEach接口基于数组类型数据进行循环渲染,可基于数组数据快速生成结构相同、内容不同的子组件,适用于动态列表、批量数据展示等场景,需与容器组件配合使用 | Phone12+ |
| LazyForEach | LazyForEach是一种懒加载渲染控制组件,从提供的数据源中按需迭代数据并创建相应组件。在大量子组件的场景下,LazyForEach与缓存列表项、动态预加载、组件复用等方法配合使用,可以进一步提升滑动帧率并降低应用内存占用。最佳实践请参考优化长列表加载慢丢帧问题。 | Phone12+ |
| Repeat | Repeat基于数组类型数据来进行循环渲染,一般与滚动容器组件配合使用。 | 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。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| arr | Array<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 模型可用。在滚动容器中使用时,框架按可视区域按需创建组件,组件滑出可视区域后销毁回收以降低内存占用。属性支持拖拽排序。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| dataSource | IDataSource | 是 | 数据源,需要开发者实现相关接口。 |
| itemGenerator | (item: any, index: number) => void | 是 | 子组件生成函数。函数体必须使用大括号;每次迭代只能且必须生成一个子组件;可用if语句,但每个分支必须创建相同类型的子组件。 |
| keyGenerator | (item: any, index: number) => string | 否 | 键值生成函数。缺省时为(item, index) => viewId + '-' + index,仅受index影响。键值需唯一且一致,否则组件复用/更新异常。 |
| options | LazyForEachOptions | 否 | 配置自定义组件冻结、内存优化策略、资源释放策略。使用时必须设置键值生成函数,否则编译失败。默认冻结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比对键值。 |
| MoveIndex | from:起始移动位置;to:目标移动位置。取值范围[0, 数据源长度-1],超出则渲染异常。 |
| ExchangeIndex | start / end:两个交换位置。取值范围[0, 数据源长度-1],超出则渲染异常。 |
| ExchangeKey | start / end:为两个交换位置分配新键值,默认使用原键值。 |
DataOperationType(API 12+)
| 名称 | 值 | 说明 |
|---|---|---|
| ADD | add | 数据添加。 |
| DELETE | delete | 数据删除。 |
| CHANGE | change | 数据改变。 |
| MOVE | move | 数据移动。 |
| EXCHANGE | exchange | 数据交换。 |
| RELOAD | reload | 全部数据重载。 |
LazyForEachOptions(26.0.0+)
| 名称 | 类型 | 可选 | 说明 |
|---|---|---|---|
| customComponentFreezeMode | LazyForEachCustomComponentFreezeMode | 是 | 是否使能自定义组件冻结,仅在LazyForEach下直接使用自定义组件时生效。默认AUTO。 |
| releaseStrategy | LazyForEachReleaseStrategy | 是 | 资源释放策略。默认BATCH,批量释放节点。 |
| memoryOptimizationStrategy | LazyForEachMemOptStrategy | 是 | 内存优化策略,创建时设定,不支持动态修改。默认DEFAULT。 |
| 枚举 | 名称 | 值 | 说明 |
|---|---|---|---|
| LazyForEachCustomComponentFreezeMode | AUTO | 0 | 跟随module.json5配置文件中metadata的设置。 |
| DISABLED | 1 | 不使能自定义组件冻结。 | |
| ENABLED | 2 | 使能自定义组件冻结。 | |
| LazyForEachReleaseStrategy | BATCH | 0 | 默认策略,当前帧释放所有废弃节点,复用率最高;节点层级深、子组件多时可能产生超大帧。 |
| PROGRESSIVE | 1 | 按当前帧剩余时间逐个释放,帧时间不足则延后,避免超大帧;但LazyForEach会继续持有节点,复用率可能下降、内存升高。 | |
| LazyForEachMemOptStrategy | DEFAULT | 0 | 无内存优化策略。 |
| ENABLE_AUTO_CACHE_OPTIMIZATION | 1 << 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。 |
| TemplateOptions | cachedCount:当前template缓存池中可缓存子组件节点的最大数量,取值[0, +∞),默认为显示区域与预加载区域节点数之和(只增不减)。推荐设为显示区域节点数,不建议小于2。 |
VirtualScrollOptions
| 名称 | 类型 | 可选 | 说明 |
|---|---|---|---|
| totalCount | number | 是 | 期望加载的数据项总数,可不等于数据源长度。与onTotalCount最多设一个,同设时忽略totalCount;缺省或超范围时取数据源长度。=0不加载数据;≤数据源长度时只渲染[0, totalCount-1];>数据源长度时需应用在临近末尾时请求后续数据,建议配合onLazyLoading。 |
| reusable | boolean | 是 | API 18+。是否开启复用功能,默认true。子组件为@ReusableV2装饰的自定义组件时,Repeat自身复用优先,若想用@ReusableV2的复用能力建议关闭。 |
| memoryOptimizationStrategy | RepeatMemOptStrategy | 是 | 26.0.0+。内存优化策略,创建时设定,不支持动态修改。默认DEFAULT。 |
| onTotalCount | () => number | 是 | API 19+。自定义计算期望加载的数据项总数,处理规则与totalCount一致;返回非自然数时由数据源长度取代。 |
| onLazyLoading | (index: number) => void | 是 | API 19+。懒加载指定索引的数据。需以arr[index] = ...写入,不允许其他数组操作或写入其他索引;执行后该index仍无数据将导致后续组件无法加载;应避免阻塞式耗时操作。 |
RepeatMemOptStrategy
| 名称 | 值 | 说明 |
|---|---|---|
| DEFAULT | 0 | 无内存优化策略。 |
| ENABLE_AUTO_CACHE_OPTIMIZATION | 1 << 0 | 自动内存优化。退后台、组件不可见、整机低内存时释放缓存池内所有节点;恢复前台或恢复显示时恢复缓存池节点,释放与恢复会触发自定义组件生命周期。 |
三者应用范围差异比较
| 维度 | ForEach | LazyForEach | Repeat |
|---|---|---|---|
| 起始版本 | 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。” 同时列了若干硬性限制,下面这些是替代不了的地方。
硬性拦路条件
- 状态管理版本。Repeat 的懒加载模式(
.virtualScroll())只支持状态管理 V2,与 V1 配合会导致渲染异常。存量工程如果还是@State/@Observed/@ObjectLink,要么先迁 V2,要么继续用 LazyForEach。这是最常见的阻塞点。- 容器范围。Repeat 懒加载只支持 List、ListItemGroup、Grid、Swiper、WaterFlow 五种容器;不在这个列表里的滚动场景用不了懒加载(关掉 virtualScroll 就退化成全量加载,失去意义)。
- 同容器混排。滚动容器内只能包含一个 Repeat,不建议同时有 ListItem、ForEach、LazyForEach,也不建议多个 Repeat。而 LazyForEach 可以和固定 ListItem 混排、多个并存——比如"头部固定项 + 懒加载列表 + 尾部加载更多"这种结构,用 Repeat 需要重构布局。
- API 版本。Repeat 从 API 12 起,
reusable18+、onTotalCount/onLazyLoading19+。要兼容 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标记属性的原始类型,可确保在序列化过程中正确保留和还原属性的复杂类型信息,适用于需要持久化或序列化复杂对象的场景,例如应用状态持久化存储、跨组件复杂数据传递等。
更多推荐



所有评论(0)