HarmonyOS Tabs框架切换问题?

使用tabs框架时,当起始页索引为0时,手动切换到索引位置未5的位置时,索引小于5的页面都执行了aboutToAppear,这样就会导致一些网络请求提前被请求了。(在aboutToAppear中添加了初始化数据的请求)

需求:当从0切换到5时,只处理5页面的初始化数据请求,是否有参数可以控制或者请求时机怎么调整合适?

阅读 501
1 个回答

当前Tabs不支持懒加载,可以使用如下方案先规避。

方案一:

@Component
struct CustomView {
  text: string = ""

  aboutToAppear(): void {
    console.info("aboutToAppear:" + this.text)
  }

  aboutToDisappear(): void {

  }

  build() {
    Column() {
      Text(this.text)
        .fontSize(50)
        .fontWeight(FontWeight.Bold)
    }
  }
}

@Entry
@Component
struct TabsTest {
  @State currentIndex: number = 0
  @State tabContentArr: boolean[] = [true, false, false, false, false, false, false, false]
  tabContents: string[] = ["首页", "推荐", "发现", "视频", "娱乐", "体育", "军事", "我的"]

  build() {
    Row() {
      Column() {
        Tabs({ barPosition: BarPosition.Start }) {
          ForEach(this.tabContents, (item: Resource, index) => {
            TabContent() {
              if (this.currentIndex === index || this.tabContentArr[index]) {
                CustomView({ text: this.currentIndex.toString() })
              }
            }.tabBar(item)
          })
        }
        .onChange((index) => {
          this.currentIndex = index
          this.tabContentArr[index] = true
        })
      }
      .width('100%')
    }
    .height('100%')
  }
}

方案二:使用Swiper+自定义一个Tab头,swiper组件支持懒加载,示例如下:https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-container-swiper-V5\#示例1

第二个方案使用Swiper当前不太友好,Swiper受限于cacheCount,可能会导致组件重新创建,不如Tabs友好,建议还是使用第一种方案。具体问题详情可以运行一下以下代码,多点几个Tab会发现已经加载过的组件依然会执行aboutToAppear。

示例代码:

class MyDataSource implements IDataSource {
  private list: string[] = []
  constructor(list: string[]) {
    this.list = list
  }

  totalCount(): number {
    return this.list.length
  }

  getData(index: number): string {
    return this.list[index]
  }

  registerDataChangeListener(listener: DataChangeListener): void {
  }

  unregisterDataChangeListener() {
  }
}

@Component
struct CustomView1 {
  text: string = ""

  aboutToAppear(): void {
    console.info("aboutToAppear:" + this.text)
  }

  build() {
    Column() {
      Text(this.text)
        .width('100%')
        .height('100%')
        .backgroundColor(0xAFEEEE)
        .textAlign(TextAlign.Center)
        .fontSize(30)
    }
  }
}

@Entry
@Component
struct SwiperTabs {
  private swiperController: SwiperController = new SwiperController()
  private tabController: TabsController = new TabsController()
  private data: MyDataSource = new MyDataSource([])
  tabContents: string[] = ["首页", "推荐", "发现", "视频", "娱乐", "体育", "军事", "我的"]
  @State @Watch("onIndexChange") index: number = 0;

  onIndexChange() {
    this.tabController.changeIndex(this.index)
    this.swiperController.changeIndex(this.index, false)
  }

  aboutToAppear(): void {
    this.data = new MyDataSource(this.tabContents)
  }

  build() {
    Column() {
      Tabs({ barPosition: BarPosition.Start, controller: this.tabController }) {
        ForEach(this.tabContents, (item: Resource, index) => {
          TabContent() {
          }.height(0).tabBar(
            new SubTabBarStyle(item)
              .labelStyle({ unselectedColor: Color.Red, selectedColor: Color.Green })
          )
        })
      }
      .height(56)
      .barHeight(56)
      .onAnimationStart((index: number, targetIndex: number, event: TabsAnimationEvent) => {
        this.index = targetIndex;
      })

      Swiper(this.swiperController) {
        LazyForEach(this.data, (item: string) => {
          CustomView1({
            text: item
          })
        }, (item: string) => item)
      }
      .cachedCount(0)
      .autoPlay(false)
      .loop(false)
      .itemSpace(0)
      .indicator(false)
      .displayArrow(false)
      .duration(500)
      .curve(Curve.Linear)
      .onChange((index: number) => {
        this.index = index;
      })
      .width('100%')
      .height("calc(100% - 56vp)")
    }.width('100%')
  }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进