HarmonyOS 鸿蒙Next中Tabs组件在翻页时页面的刷新问题

HarmonyOS 鸿蒙Next中Tabs组件在翻页时页面的刷新问题 为了方便讨论,我们不妨使用官方案例来说明,链接如下:示例3自定义页签切换联动

案例中,所有tabContent的内容都是在一个ets文件中。

image.png

所以,页面滚动效果都没问题。

cke_4606.gif


但是,如果我稍加改动,将原先tabContent的内容拆分到4个ets文件中,其他什么代码都不动

image.png

问题出现了!只有当页签滚动到位后,页面内容才触发刷新。

cke_13732.gif

这是为什么呀?

代码如下:

import { test1 } from './test1';
import { test2 } from './test2';
import { test3 } from './test3';
import { test4 } from './test4';

interface tabBarClass {
  index: number
  name: string
  bgc: string
}

@Entry
@Component
struct TabsExample {
  @State fontColor: string = '#182431';
  @State selectedFontColor: string = '#007DFF';
  @State currentIndex: number = 0;
  @State selectedIndex: number = 0;
  private controller: TabsController = new TabsController();
  private tabBarItems: tabBarClass[] = [
    { index: 0, name: 'green', bgc: '#00CB87' },
    { index: 1, name: 'blue', bgc: '#007DFF' },
    { index: 2, name: 'yellow', bgc: '#FFBF00' },
    { index: 3, name: 'pink', bgc: '#E67C92' }
  ]

  @Builder
  tabBuilder(index: number, name: string) {
    Column() {
      Text(name)
        .fontColor(this.selectedIndex === index ? this.selectedFontColor : this.fontColor)
        .fontSize(16)
        .fontWeight(this.selectedIndex === index ? 500 : 400)
        .lineHeight(22)
        .margin({ top: 17, bottom: 7 })
      Divider()
        .strokeWidth(2)
        .color('#007DFF')
        .opacity(this.selectedIndex === index ? 1 : 0)
    }.width('100%')
  }

  build() {
    Column() {
      Tabs({ barPosition: BarPosition.Start, index: this.currentIndex, controller: this.controller }) {
        /*
                ForEach(this.tabBarItems, (item: tabBarClass, index: number) => {
                  TabContent() {
                    if (this.currentIndex === 0) {
                      test1()
                    } else if (this.currentIndex === 1) {
                      test2()
                    } else if (this.currentIndex === 2) {
                      test3()
                    } else if (this.currentIndex === 3) {
                      test4()
                    }
                  }.tabBar(this.tabBuilder(item.index, item.name))
                })
        */

        TabContent() {
          Column().width('100%').height('100%').backgroundColor('#00CB87')
        }.tabBar(this.tabBuilder(0, 'green'))

        TabContent() {
          Column().width('100%').height('100%').backgroundColor('#007DFF')
        }.tabBar(this.tabBuilder(1, 'blue'))


        TabContent() {
          Column().width('100%').height('100%').backgroundColor('#FFBF00')
        }.tabBar(this.tabBuilder(2, 'yellow'))


        TabContent() {
          Column().width('100%').height('100%').backgroundColor('#E67C92')
        }.tabBar(this.tabBuilder(3, 'pink'))
      }
      .vertical(false)
      .barMode(BarMode.Fixed)
      .barWidth(360)
      .barHeight(56)
      .animationDuration(400)
      .onChange((index: number) => {
        // currentIndex控制TabContent显示页签
        this.currentIndex = index;
        this.selectedIndex = index;
      })
      .onAnimationStart((index: number, targetIndex: number, event: TabsAnimationEvent) => {
        if (index === targetIndex) {
          return;
        }
        // selectedIndex控制自定义TabBar内Image和Text颜色切换
        this.selectedIndex = targetIndex;
      })
      .width(360)
      .height(296)
      .margin({ top: 52 })
      .backgroundColor('#F1F3F5')
    }.width('100%')
  }
}

其中,TabContent中涉及的4个页面都很简单,大致如下:

@Entry
@Component
export struct test1 {

  build() {
    Column().width('100%').height('100%').backgroundColor('#00CB87')
  }
}

更多关于HarmonyOS 鸿蒙Next中Tabs组件在翻页时页面的刷新问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

你好。

这是写法使用的问题。首先Tabs容器作为页签容器,里面的页签对应的是TabContent。一个页签就是一个Content。

image.png

所以你想把页签抽离出来写是ok的,只不过在主页面要把TabContent留下,把里面的内容抽离成自定义组件。

Tabs() {
  TabContent() {
  this.APage()
  }
  .tabBar('首页')

  TabContent() {
  this.BPage()
  }
  .tabBar('推荐')

  TabContent() {
    this.CPage()
  }
  .tabBar('发现')
  
  TabContent() {
      this.DPage()
  }
  .tabBar("我的")
}

更多关于HarmonyOS 鸿蒙Next中Tabs组件在翻页时页面的刷新问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,Tabs组件切换时默认会触发页面的重新渲染。若需控制刷新行为,可使用@State@Prop装饰器管理组件状态。通过onChange事件监听Tab切换,结合条件渲染避免不必要的刷新。对于数据更新,推荐使用@Link实现父子组件数据同步。若需保持页面状态,可配合LazyForEachcachedCount属性优化性能。Tabs的preload属性可预加载相邻页内容。

这个问题是由于组件加载机制导致的。在HarmonyOS Next中,当TabContent内容拆分到不同文件时,系统会按需加载这些组件,而不是预加载。

关键点分析:

  1. 单文件情况下,所有TabContent内容已预加载,切换时直接显示
  2. 多文件情况下,TabContent作为独立组件,会在实际需要显示时才触发加载
  3. 当前实现中,Tab切换动画和内容加载是同步进行的

解决方案建议:

  1. 使用预加载机制,在Tabs初始化时提前加载所有TabContent组件
  2. 或者在onChange回调中主动触发内容更新,而不是依赖系统自动刷新

代码修改方向:

// 提前声明组件引用
private tabComponents = [test1, test2, test3, test4]

// 在build方法中使用动态组件
ForEach(this.tabBarItems, (item: tabBarClass) => {
  TabContent() {
    this.tabComponents[item.index]()
  }.tabBar(this.tabBuilder(item.index, item.name))
})

这种实现方式可以保证组件提前加载,避免切换时的延迟问题。

回到顶部