HarmonyOS list的item如何保存状态

目前我有一个list,item自定义@Component布局,通过设置item的值初始化item数据,item中有@state状态用于标识item是否点击,现在问题是我点击了item,然后滑动列表到后面数据,滑动回来后,这个状态丢失了,该如何保存这个状态呢?

HarmonyOS
2024-09-26 11:05:46
浏览
收藏 0
回答 2
待解决
回答 2
按赞同
/
按时间
鱼弦CTO
1

在HarmonyOS中,当你使用列表(如 ​​List​​​ 或 ​​LazyForEach​​)显示大量数据时,列表项会根据需要进行回收和重用。这意味着在滚动离开视图区域后,再次滚动回来时,之前的状态可能会丢失。

为了保持每个列表项的状态,即使在滚动后也能恢复,你可以将这些状态保存在全局状态管理中,而不是在每个列表项组件中维护本地状态。一个常见的方法是使用 ​​@State​​ 或 ​​@Observed​​ 类来保存状态,并确保其与列表项的唯一标识相关联。

### 示例代码

#### 定义Item状态类 首先,定义一个状态类,用于存储每个列表项的状态:

@Observed
class ItemState {
    id: string;
    isClicked: boolean;

    constructor(id: string, isClicked: boolean = false) {
        this.id = id;
        this.isClicked = isClicked;
    }
}

#### 父组件保存并管理列表项的状态

在父组件中,使用一个 ​​@State​​ 属性来存储所有列表项的状态:

@Entry
@Component
struct MyListPage {
    @State private items: Array<ItemData> = [];
    @State private itemStates: Map<string, ItemState> = new Map<string, ItemState>();

    aboutToAppear() {
        // 初始化数据
        this.items = [
            { id: '1', text: 'Item 1' },
            { id: '2', text: 'Item 2' },
            { id: '3', text: 'Item 3' },
            // 添加更多数据...
        ];

        // 初始化状态
        this.items.forEach(item => {
            this.itemStates.set(item.id, new ItemState(item.id));
        });
    }

    build() {
        Column() {
            List() {
                ForEach(this.items, (item: ItemData) => {
                    ListItem() {
                        MyListItemComponent({
                            data: item,
                            state: this.itemStates.get(item.id)!
                        })
                    }
                }, (item: ItemData) => item.id)
            }
        }
    }

    handleItemClick(itemId: string) {
        const state = this.itemStates.get(itemId);
        if (state) {
            state.isClicked = !state.isClicked;
        }
    }
}

#### 自定义列表项组件 自定义列表项组件接收 ​​data​​ 和 ​​state​​ 作为属性,并在适当的时候更新状态:

@Component
struct MyListItemComponent {
    @Prop data: ItemData;
    @Prop state: ItemState;

    build() {
        Column() {
            Text(this.data.text)
            Button("Toggle State")
                .onClick(() => {
                    this.state.isClicked = !this.state.isClicked;
                })
                .backgroundColor(this.state.isClicked ? Color.Green : Color.Red)
        }
        .padding(16)
        .margin({ bottom: 10 })
        .borderRadius(8)
        .backgroundColor(Color.White)
    }
}

### 数据模型 定义你的数据模型:

class ItemData {
    id: string;
    text: string;

    constructor(id: string, text: string) {
        this.id = id;
        this.text = text;
    }
}

### 总结

  • 全局状态:将每个列表项的状态存储在父组件的全局状态中(例如​​Map​​)。
  • 统一管理:通过​​id​​ 将状态与列表项关联,使得即便在滚动之后,每个列表项的状态都能被正确恢复。
  • 状态传递:将列表项的数据和状态通过​​@Prop​​ 传递给子组件,并在子组件内进行状态的渲染和更新。

通过这种方式,可以确保在列表滚动、回收和重用过程中,每个列表项的状态不会丢失。

分享
微博
QQ
微信
回复
2024-09-26 19:03:02
zbw_apple
@Entry  
@Component  
struct Index {  
  @State messageArr: string[] = [];  
  scroller: Scroller = new Scroller()  
  aboutToAppear(): void {  
    for (let index = 0; index < 20; index++) {  
      this.messageArr.push(index.toString())  
    }  
  }  
  build() {  
    Scroll(this.scroller) {  
      // 布局  
      Column(){  
        ForEach(this.messageArr, (item:string,index:number) => {  
          Text(item)  
            .width("100%")  
            .height(100)  
            .backgroundColor(Color.Pink)  
            .margin({  
              bottom:20  
            })  
            .onClick(()=>{  
              this.messageArr[index] = "change"  
            })  
  
        }, (item:string) => JSON.stringify(item))  
      }  
  
    }  
  }  
}
分享
微博
QQ
微信
回复
2024-09-26 17:46:37
相关问题
HarmonyOSList如何加载item
184浏览 • 2回复 待解决
HarmonyOS List item 刷新问题
732浏览 • 1回复 待解决
HarmonyOS listitem交互效果处理
347浏览 • 1回复 待解决
HarmonyOS listitem支持托动效果吗?
244浏览 • 1回复 待解决
怎么获取List里面每个itemposition?
256浏览 • 1回复 待解决
listadd跟remove item入场、出场动画
1208浏览 • 1回复 待解决
Listitem点击变色有什么好方法吗
2152浏览 • 1回复 待解决
list-item 根据boolean属性 动态设置class
4820浏览 • 1回复 待解决
JS swiper 怎么像list一样动态添加item
6327浏览 • 1回复 待解决