二十五、【鸿蒙 NEXT】@ObservedV2/@Trace实现组件动态刷新

【前言】

之前在"
十一、【鸿蒙 NEXT】@Observed装饰器和@ObjectLink装饰器"这边文章中介绍了如何动态刷新列表数据,由于@Observed状态的刷新还是有很多限制,比如父组件持有的是数组对象,想要动态刷新,则无法实现等,这里介绍一个功能强大的状态类型@ObservedV2/@Trace的使用方式,更加简洁,且效率更高,这里结合LazyFoeach的使用,来实现列表数据的动态刷新

1、我们首先看下LazyFoeach的接口定义

其实和Foreach差不多,只不过第一个参数是一个IDataSource对象,而不是一个数组对象。列表的刷新机制也和Foreach一样,如果第三个参数生成的key变化了,就会销毁老的组件,重新创建新的组件。但是这种方式和第十一章的Foreach刷新一样会导致图片闪烁的问题。因此下面介绍下

@ObservedV2/@Trace动态刷新每个列表的子组件

2、@ObservedV2/@Trace动态刷新

使用@ObservedV2动态刷新

(1)首先定义消息对象,也就是数组中的消息类型,声明@ObservedV2,同时对于需要动态刷新的属性声明@Trace
(2)对于LazyForeach的第三个参数,直接用Message中的id作为每个item的key,只要id不变,就不重新创建子组件,这样能保证不会出现图片闪烁的情况
(3)刷新数据时,直接找到对应id的数据,修改name值,就会实现刷新
实现效果如下,这里图片不会出现闪烁情况:

使用LazyForeach的key值变更实现刷新:

(1)在上面基础上,将LazyForeach的第三个参数改为对Message的json序列化字符串
(2)找到对应id的index,然后修改对应index的值,刷新数据:
LazyForeach的key值变更实现刷新效果如下,会出现图片闪烁情况:

@ObservedV2/@Trace完整代码如下:

javascript 复制代码
import { DateSource } from './DateSource'

@Entry
@ComponentV2
struct LazyForeachPage {
  dataSource: DateSource<Message> = new DateSource()
  private index = 1

  aboutToAppear(): void {
    let data1 = new Message()
    data1.id = '1'
    data1.name = '张三'
    data1.icon = $r('app.media.touxiang1')
    let data2 = new Message()
    data2.id = '2'
    data2.name = '张四'
    data2.icon = $r('app.media.touxiang1')
    let data3 = new Message()
    data3.id = '3'
    data3.name = '张五'
    data3.icon = $r('app.media.touxiang1')
    this.dataSource.addItems([data1,data2,data3])
  }

  build() {
    Column(){
      Button('ObservedV2刷新').onClick(() => {
        this.index++
        this.dataSource.getAllData().find(item => item.id === '3')!.name = `张${this.index}`
      })
      // Button('原始刷新').onClick(() => {
      //   this.index++
      //   this.dataSource.changeData(2,{id:'3', name: `张${this.index}`, icon:$r('app.media.touxiang1')} as Message)
      // })
      List({space:10}) {
        LazyForEach(this.dataSource, (item:Message)=> {
         ListItem() {
           Row(){
             Image(item.icon).height(40).width(40)
             Text(item.name)
           }
         }
        }, (item:Message) => item.id)
      }
    }
    .padding({left:32})
    .height('100%')
    .width('100%')
  }
}

@ObservedV2
class Message {
  id:string = ''
  @Trace name:string = ''
  icon:ResourceStr = ''
}

dataSource代码如下

javascript 复制代码
export class DateSource<T> implements IDataSource{
  private dataArray: T[] = [];
  private listeners: DataChangeListener[] = [];
  // 该方法为框架侧调用,为LazyForEach组件向其数据源处添加listener监听
  registerDataChangeListener(listener: DataChangeListener): void {
    if (this.listeners.indexOf(listener) < 0) {
      this.listeners.push(listener);
    }
  }

  // 该方法为框架侧调用,为对应的LazyForEach组件在数据源处去除listener监听
  unregisterDataChangeListener(listener: DataChangeListener): void {
    const pos = this.listeners.indexOf(listener);
    if (pos >= 0) {
      this.listeners.splice(pos, 1);
    }
  }
  public totalCount(): number {
    return this.dataArray.length;
  }

  public getData(index: number): T {
    return this.dataArray[index];
  }

  public getAllData(): T[] {
    return this.dataArray;
  }

  // 通知LazyForEach组件需要重载所有子组件
  notifyDataReload(): void {
    this.listeners.forEach(listener => {
      listener.onDataReloaded();
    });
  }

  // 通知LazyForEach组件需要在index对应索引处添加子组件
  notifyDataAdd(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataAdd(index);
    });
  }

  // 通知LazyForEach组件在index对应索引处数据有变化,需要重建该子组件
  notifyDataChange(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataChange(index);
    });
  }

  public changeData(index: number, data: T): void {
    this.dataArray.splice(index, 1, data);
    this.notifyDataChange(index);
  }

  public refreshItems(list: T[]): void {
    this.dataArray = [...list]
    this.notifyDataReload()
  }

  public addItems(list:T[]) {
    list.forEach(item => {
      this.dataArray.push(item)
      this.notifyDataAdd(this.dataArray.length - 1)
    })
  }
}
相关推荐
wszy18092 小时前
rn_for_openharmony_空状态与加载状态:别让用户对着白屏发呆
android·javascript·react native·react.js·harmonyos
SameX2 小时前
鸿蒙应用的“任意门”:Deep Linking 与 App Linking 的相爱相杀
harmonyos
AlbertZein2 小时前
HarmonyOS一杯冰美式的时间 -- @Watch 到 @Monitor
harmonyos
奋斗的小青年!!3 小时前
Flutter跨平台开发适配OpenHarmony:下拉刷新组件的实战优化与深度解析
flutter·harmonyos·鸿蒙
lili-felicity3 小时前
React Native for Harmony:订单列表页面状态筛选完整实现
react native·react.js·harmonyos
lili-felicity4 小时前
React Native 鸿蒙跨平台开发:纯原生IndexBar索引栏 零依赖 快速定位列表
react native·react.js·harmonyos
小雨下雨的雨5 小时前
Flutter鸿蒙共赢——秩序与未知的共鸣:彭罗斯瓷砖在鸿蒙律动中的数字重构
flutter·华为·重构·交互·harmonyos·鸿蒙系统
2501_948122635 小时前
rn_for_openharmony_steam资讯app实战-标签游戏列表实现
react.js·游戏·harmonyos
行者965 小时前
Flutter适配OpenHarmony:个人中心
flutter·harmonyos·鸿蒙