HarmonyOS 组件复用 @ReusableV2 装饰器的基本使用 2
2025-06-26 11:55:39
108次阅读
0个评论
HarmonyOS 组件复用 @ReusableV2 装饰器的基本使用 2
前言
接上文 HarmonyOS 组件复用 @ReusableV2 装饰器的基本使用
上文已经介绍过了 @ReusableV2 的基本使用和生命周期,本文主要讲解**@ReusableV2**的使用场景
使用场景
如官网中所总结的,因为以下场景都经常伴随着组件的显示和隐藏,@ReusableV2 常见的使用场景如下:
- 搭配 if 使用
- 搭配 Repeat 使用
- 搭配 ForEach 使用
- 搭配 LazyForEach 使用
搭配 if 使用
@Entry
@ComponentV2
struct Index {
@Local condition: boolean = true;
build() {
Column() {
Button('回收/复用').onClick(() => {
this.condition = !this.condition;
}) // 点击切换回收/复用状态
if (this.condition) {
ReusableV2Component()
}
}
}
}
@ReusableV2
@ComponentV2
struct ReusableV2Component {
@Local message: string = 'Hello World';
aboutToRecycle() {
console.log('ReusableV2Component aboutToRecycle'); // 回收时被调用
}
aboutToReuse() {
console.log('ReusableV2Component aboutToReuse'); // 复用时被调用
}
build() {
Column() {
Text(this.message)
}
}
}
效果
搭配 Repeat each 使用 懒加载场景
Repeat 组件懒加载场景中,将会优先使用 Repeat 组件的缓存池,正常滑动场景、更新场景不涉及组件的回收与复用。当 Repeat 的缓存池需要扩充时将会向自定义组件要求新的子组件,此时如果复用池中有可复用的节点,将会进行复用。
@Entry
@ComponentV2
struct Index {
@Local condition: boolean = true;
@Local simpleList: number[] = [];
aboutToAppear(): void {
for (let i = 0; i < 100; i++) {
this.simpleList.push(i)
}
}
build() {
Column() {
Button('改变condition').onClick(() => {
this.condition = !this.condition;
})
if (this.condition) {
// 此处仅做演示使用,让复用池中填充3个组件
ReusableV2Component({ num: 0 })
ReusableV2Component({ num: 0 })
ReusableV2Component({ num: 0 })
}
List({ space: 10 }) {
Repeat(this.simpleList)
.virtualScroll()
.each((obj: RepeatItem<number>) => {
ListItem() {
Column() {
ReusableV2Component({ num: obj.item })
}
}
})
}.height('50%')
.cachedCount(2)
}
}
}
@ReusableV2
@ComponentV2
struct ReusableV2Component {
@Require @Param num: number;
aboutToAppear() {
console.log('ReusableV2Component aboutToAppear');
}
aboutToRecycle() {
console.log('ReusableV2Component aboutToRecycle');
}
aboutToReuse() {
console.log('ReusableV2Component aboutToReuse');
}
build() {
Column() {
Text(`${this.num}`).fontSize(50)
}
}
}
效果
步骤解释:
- 正常滑动列表,不会触发组件的 回收和复用
- 点击按钮,条件渲染 组件时,就会触发组件的回收和复用了
virtualScroll
virtualScroll 表示 虚拟列表,使用不使用 virtualScroll 的区别在于
使用 virtualScroll | 不使用 virtualScroll |
---|---|
预加载区的 ListItem 会在系统空闲时创建和布局 | 预加载区内的 ListItem 会在首帧创建,系统空闲时布局 ListItem 和创建 ListItem 内部的子结构 |
使用 virtualScroll :
不使用 virtualScroll :
搭配 Repeat each 使用 非懒加载场景
Repeat 组件非懒加载场景中,会在删除/创建子树时触发回收/复用。
@Entry
@ComponentV2
struct Index {
@Local simpleList: number[] = [1, 2, 3, 4, 5];
@Local condition: boolean = true;
build() {
Column() {
Button('删除/创建Repeat').onClick(() => {
this.condition = !this.condition;
})
Button('增加元素').onClick(() => {
this.simpleList.push(this.simpleList.length + 1);
})
Button('删除元素').onClick(() => {
this.simpleList.pop();
})
Button('更改元素').onClick(() => {
this.simpleList[0]++;
})
if (this.condition) {
List({ space: 10 }) {
Repeat(this.simpleList)
.each((obj: RepeatItem<number>) => {
ListItem() {
Column() {
ReusableV2Component({ num: obj.item })
}
}
})
}
}
}
}
}
@ReusableV2
@ComponentV2
struct ReusableV2Component {
@Require @Param num: number;
aboutToAppear() {
console.log('ReusableV2Component aboutToAppear');
}
aboutToRecycle() {
console.log('ReusableV2Component aboutToRecycle');
}
aboutToReuse() {
console.log('ReusableV2Component aboutToReuse');
}
build() {
Column() {
Text(`${this.num}`)
}
}
}
操作步骤如下:
-
运行项目
触发 aboutToAppear
-
增加元素
触发 aboutToAppear
-
删除元素
触发 aboutToRecycle
-
更改元素
无输出
-
删除/创建 Repeat
触发 aboutToRecycle 和 aboutToReuse
搭配 Repeat 和 ForEach
推荐开发者使用 Repeat 组件的非懒加载场景代替 ForEach 组件
@Entry
@ComponentV2
struct Index {
@Local simpleList: number[] = [0, 1, 2, 3, 4, 5];
build() {
Column() {
ForEach(this.simpleList, (num: number, index) => {
Row() {
Button('点击修改').onClick(()=>{this.simpleList[index]++;})
ReusableV2Component({ num: num })
}
}) // 每次修改完key发生变化
}
}
}
@ReusableV2
@ComponentV2
struct ReusableV2Component {
@Require @Param num: number;
aboutToAppear() {
console.log('ReusableV2Component aboutToAppear', this.num); // 创建时触发
}
aboutToRecycle() {
console.log('ReusableV2Component aboutToRecycle', this.num); // 回收时触发
}
aboutToReuse() {
console.log('ReusableV2Component aboutToReuse', this.num); // 复用时触发
}
build() {
Column() {
Text(`child: ${this.num}`)
}
}
}
搭配 Repeat 和 LazyForEach
推荐开发者使用 Repeat 组件的懒加载场景代替 LazyForEach 组件
class BasicDataSource implements IDataSource {
private listeners: DataChangeListener[] = [];
private originDataArray: StringData[] = [];
public totalCount(): number {
return 0;
}
public getData(index: number): StringData {
return this.originDataArray[index];
}
registerDataChangeListener(listener: DataChangeListener): void {
if (this.listeners.indexOf(listener) < 0) {
console.info('add listener');
this.listeners.push(listener);
}
}
unregisterDataChangeListener(listener: DataChangeListener): void {
const pos = this.listeners.indexOf(listener);
if (pos >= 0) {
console.info('remove listener');
this.listeners.splice(pos, 1);
}
}
notifyDataReload(): void {
this.listeners.forEach(listener => {
listener.onDataReloaded();
})
}
notifyDataAdd(index: number): void {
this.listeners.forEach(listener => {
listener.onDataAdd(index);
})
}
notifyDataChange(index: number): void {
this.listeners.forEach(listener => {
listener.onDataChange(index);
})
}
notifyDataDelete(index: number): void {
this.listeners.forEach(listener => {
listener.onDataDelete(index);
})
}
notifyDataMove(from: number, to: number): void {
this.listeners.forEach(listener => {
listener.onDataMove(from, to);
})
}
notifyDatasetChange(operations: DataOperation[]): void {
this.listeners.forEach(listener => {
listener.onDatasetChange(operations);
})
}
}
class MyDataSource extends BasicDataSource {
private dataArray: StringData[] = [];
public totalCount(): number {
return this.dataArray.length;
}
public getData(index: number): StringData {
return this.dataArray[index];
}
public addData(index: number, data: StringData): void {
this.dataArray.splice(index, 0, data);
this.notifyDataAdd(index);
}
public pushData(data: StringData): void {
this.dataArray.push(data);
this.notifyDataAdd(this.dataArray.length - 1);
}
}
@ObservedV2
class StringData {
@Trace message: string;
constructor(message: string) {
this.message = message;
}
}
@Entry
@ComponentV2
struct Index {
data: MyDataSource = new MyDataSource(); // 数据源
aboutToAppear() {
for (let i = 0; i <= 200; i++) {
this.data.pushData(new StringData('Hello' + i));
}
}
build() {
List({ space: 3 }) {
LazyForEach(this.data, (item: StringData, index: number) => {
ListItem() {
Column() {
Text(item.message)
ChildComponent({ data: item.message })
.onClick(() => {
item.message += '!'; // message为@Trace装饰的变量,可观察变化
})
}
}
})
}.cachedCount(5)
}
}
@ReusableV2
@ComponentV2
struct ChildComponent {
@Param @Require data: string;
aboutToAppear(): void {
console.log('ChildComponent aboutToAppear', this.data);
}
aboutToDisappear(): void {
console.log('ChildComponent aboutToDisappear', this.data);
}
aboutToReuse(): void {
console.log('ChildComponent aboutToReuse', this.data); // 复用时触发
}
aboutToRecycle(): void {
console.log('ChildComponent aboutToRecycle', this.data); // 回收时触发
}
build() {
Row() {
Text(this.data).fontSize(50)
}
}
}
关于我们
如果你兴趣想要了解更多的鸿蒙应用开发细节和最新资讯,甚至你想要做出一款属于自己的应用!欢迎在评论区留言或者私信或者看我个人信息,可以加入技术交流群。
00
- 0回答
- 6粉丝
- 1关注
相关话题
- HarmonyOS 组件复用 @ReusableV2 装饰器的基本使用
- HarmonyOS 组件复用 @Reusable 装饰器的基本使用
- @ComponentV2装饰器:自定义组件
- HarmonyOS Next V2 状态管理@ObservedV2基本使用
- 鸿蒙开发:V2版本装饰器之@Monitor装饰器
- 【HarmonyOS 5】鸿蒙的装饰器原理和自定义装饰器
- 【HarmonyOS 5】鸿蒙的装饰器原理和自定义装饰器
- 鸿蒙开发:刷新库V2装饰器适配
- 鸿蒙开发:V2版本装饰器@Once
- 鸿蒙开发:组件样式的复用
- 【HarmonyOS NEXT】ArkTs函数、类、接口、泛型、装饰器解析与使用
- harmony OS NEXT-基本介绍及DevcoStudiop基本使用
- Repeat:子组件复用
- 【HarmonyOS】深入理解@Observed装饰器和@ObjectLink装饰器:嵌套类对象属性变化
- 鸿蒙HarmonyOS ArkTS @Track装饰器详解