HarmonyOS Tabs使用$$双向绑定索引,导致数据源在更新时索引重置为0?

如描述,在一个刷新场景,当前Tabs索引已经非0,触发刷新后,更新Tabs绑定的List数据源,更新后Tabs内部更新索引为0。

【问题】如何在更新数据源的同时,不引起索引的变化,还保持当前索引选中?

Tips:

为了保证tab刷新,重新了Tabs中ForEach的keyGenerator,每次都是uuid

核心代码如下:

定义NCTabs

@Link @Watch("onIndexChanged") currentIndex: number
@Prop @Watch("adjustBarPosition") private tabs: Array<NCAny> = []

Tabs({ index: $$this.currentIndex, barPosition: BarPosition.Start, controller: this.tabController }) {
  ForEach(this.tabs, (item: NCAny, index: number) => {
    TabContent() {
      this.tabContentBuilder(index, item)
    }
  }, (item: NCAny, index) => this.tabContentId(index, item))
}
.onChange((index: number) => {
  Logger.logD("homerecommendonchange:" + index)
  this.currentIndex = index  // 监听索引index的变化,实现页签内容的切换。
})

onIndexChanged(changedPropertyName: string) {
  Logger.logD("onIndexChanged")
}

申明并使用View

@Builder
tabBuilder() {
  NCTabs({
    tabs: this.tabList,
    currentIndex: this.currentTabIndex,
    initIndex: this.currentTabIndex,
    tabContentBuilder: (index: number, item: NCAny) => {
      this.tabContentBuild(index, item as HomeTabs)
    },
    tabBarItemBuilder: (index: number, item: NCAny) => {
      this.tabBarBuilder(this.tabList[index].tagName, index)
    },
    tabContentId: (index, item) => {return util.generateRandomUUID()}
  })
}

获取数据并刷新

checkTabs(force: boolean): Promise<Array<HomeTabs> | null> {
  return new Promise<Array<HomeTabs> | null>((resolve) => {
  if (force || !this.remoteTabs) {
  this.mModel.getHomeTabsV2({
    onSuccess: (tabData) => {
      if (tabData && tabData.tabs) {
        this.tabList = HomeUtils.defaultHomeTabs().concat(tabData.tabs)
      }
    },
    onFinish: () => {
      // todo
      // this.refreshController.finishRefresh()
      resolve(this.tabList)
    }
  })
} else {
  resolve(this.tabList)
}
})
}
阅读 495
1 个回答

以下demo,可以直接运行,切换到其他tab后,点击refresh,索引重置到0

@Entry
@Component
struct Second {

  @State private tabs: Array<string> = []
  @State currentIndex: number = 0;
  private index = 0
  private tabsController: TabsController = new TabsController()

  build() {
    Column() {
      Button() {
        Text('Refresh')
          .fontSize(25)
          .fontWeight(FontWeight.Bold)
          .textAlign(TextAlign.Center)
      }
      .type(ButtonType.Capsule)
      .margin({
        top: 10
      })
      .backgroundColor('#0D9FFB')
      .width('40%')
      .height('5%')
      .onClick(() => {
        this.reloadTabs()
      })

      this.tabBuilder()
    }.width("100%")
  }

  @Builder
  tabBuilder() {
    Tabs({ controller: this.tabsController, index: $$this.currentIndex }) {
      ForEach(this.tabs, (item: string, index: number) => {
        TabContent() {
          Text(item).width('100%').height('100%')
        }.tabBar(item)
      })
    }.width('100%')
    .height('100%')
    .barPosition(BarPosition.Start)
    .scrollable(false)
    .barMode(BarMode.Fixed)
    .barHeight(50)
    .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
    .onChange((index: number) => {
      // this.currentIndex = index
    })
    .onTabBarClick((index) => {
      this.currentIndex = index
    })
  }

  aboutToAppear(): void {
    this.reloadTabs()
  }

  reloadTabs() {
    let temp: Array<string> = []
    for (let index = 0; index < 5; index++) {
      temp.push("Tab" + this.index + "-" + index)
    }
    this.tabs = temp
    this.index++
  }
}

@Entry
@Component
struct Second {

  @State tabs: Array<string> = []
  @State currentIndex: number = 0;
  private index = 0
  private tabsController: TabsController = new TabsController()

  build() {
    Column() {
      Button() {
        Text('Refresh')
          .fontSize(25)
          .fontWeight(FontWeight.Bold)
          .textAlign(TextAlign.Center)
      }
      .type(ButtonType.Capsule)
      .margin({
        top: 10
      })
      .backgroundColor('#0D9FFB')
      .width('40%')
      .height('5%')
      .onClick(() => {
        this.reloadTabs()
      })

      this.tabBuilder()
    }.width("100%")
  }
  @Builder tabBuilder2(index: number, name: string) {
    Column() {
      Text(name)
        .fontColor(this.currentIndex === index ? Color.Red : Color.Blue)
        .fontSize(16)
        .fontWeight(this.currentIndex === index ? 500 : 400)
        .lineHeight(22)
        .margin({ top: 17, bottom: 7 })
      Divider()
        .strokeWidth(2)
        .color('#007DFF')
        .opacity(this.currentIndex === index ? 1 : 0)
    }.width('100%')
  }
  @Builder
  tabBuilder() {
    Tabs({ controller: this.tabsController, index: $$this.currentIndex }) {
      ForEach(this.tabs, (item: string, index: number) => {
        TabContent() {
          Text(item).width('100%').height('100%')
        }.tabBar(this.tabBuilder2(index,item))
      }, (item:string) => item)

    }.width('100%')
    .height('100%')
    .barPosition(BarPosition.Start)
    .scrollable(false)
    .barMode(BarMode.Fixed)
    .barHeight(50)
    .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
    .onChange((index: number) => {
    })
    .onTabBarClick((index) => {
      this.currentIndex = index
    })
  }

  aboutToAppear(): void {
    this.reloadTabs()
  }

  reloadTabs() {
    this.tabs = []
    for (let index = 0; index < 5; index++) {
      this.tabs.push("Tab" + this.index + "-" + index)
    }
    this.index++
  }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进