HarmonyOS鸿蒙Next中Tabs组件切换onChange后为啥currentTabIndex会被重置0

HarmonyOS鸿蒙Next中Tabs组件切换onChange后为啥currentTabIndex会被重置0

import { common } from '@kit.AbilityKit'
import {
  TABBAR_TYPE,
  TABBAR_LIST,
  type TabBarListItemType
} from '../../../constants'
import {
  configSystemBar,
  throttle
} from '../../../utils'
import { Recommend, Moment, Find, Mine } from './components'

@Builder
export function LayoutBuilder() {
  Layout()
}
@Component
export struct Layout {
  pathStack: NavPathStack = new NavPathStack()
  private tabsController: TabsController = new TabsController()
  @State currentTabIndex: number = 0
  @State currentTabKey:number = TABBAR_TYPE.recommend

  /**
   * @function 生命周期-初始化数据(页面即将出现)
   */
  aboutToAppear() {
    // 修改状态栏信息
    configSystemBar(
      getContext() as common.UIAbilityContext,
      // { bgColor: '#3b3f42' }
    )
  }

  /**
   * @function tabBar项切换组件
   * @param info
   */
  @Builder tabBarItemBuilder (info: TabBarListItemType, index:number) {
    Column({ space: 5 }) {
      Image($r(info.icon))
        .width(24)
        .fillColor(this.currentTabIndex === index ? '#fc5f47' : '#63aaaa')
      Text(info.name)
        .fontSize(14)
        .fontColor(this.currentTabIndex === index ? '#fc5f47' : '#63aaaa')
    }
  }
  /**
   * @function tabBar项内容组件
   * @param info
   */
  @Builder tabBarItemContentBuilder (info: TabBarListItemType) {
    Row() {
      if (info.key === TABBAR_TYPE.recommend) {
        Recommend()
      } else if (info.key === TABBAR_TYPE.moment) {
        Moment()
      } else if (info.key === TABBAR_TYPE.find) {
        Find()
      } else if (info.key === TABBAR_TYPE.mine) {
        Mine()
      }
    }
      .width('100%')
      .height('100%')
      .backgroundColor('#000')
  }
  /**
   * @function  节流处理tab切换(优化高频点击)
   */
  private handleTabChange = throttle((index: number) => {
    if (index >= 0 && index < TABBAR_LIST.length) {
      // 更新状态
      this.currentTabIndex = index
      this.currentTabKey = TABBAR_LIST[index].key
      // 通过 controller 切换标签
      this.tabsController.changeIndex(index)
    }
  }, 200)
  build() {
    NavDestination() {
      Row() {
        Tabs({
          barPosition: BarPosition.End,
          index: this.currentTabIndex,
          controller: this.tabsController
        }) {
          ForEach(TABBAR_LIST, (tab: TabBarListItemType, index: number) => {
            // tabBar显示内容区域
            TabContent() {
              this.tabBarItemContentBuilder(tab)
            }
            // tabBar切换区域
            .tabBar(this.tabBarItemBuilder(tab, index))
          })
        }
        .backgroundColor('#3b3f42')
        .onChange((index: number) => {
          console.log('change-index', index)
          // 防止循环调用
          if (index !== this.currentTabIndex) {
            this.handleTabChange(index)
          }
        })
      }
        .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
        .backgroundColor('#000')
        .width('100%')
        .height('100%')
    }
      .hideTitleBar(true)

      .onReady((context: NavDestinationContext) => {
        this.pathStack = context.pathStack
      })
  }
}

更多关于HarmonyOS鸿蒙Next中Tabs组件切换onChange后为啥currentTabIndex会被重置0的实战教程也可以访问 https://www.itying.com/category-93-b0.html

4 回复

会不会是同时用了 index 和 controller,但没有做好状态同步,导致 onChange 事件触发时出现了冲突

更多关于HarmonyOS鸿蒙Next中Tabs组件切换onChange后为啥currentTabIndex会被重置0的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


和这个没关系,原因是NavDestination路由容器问题。上一个页面跳转到Tabs组件页之前,有定时任务导致重复更新Tabs页面,导致currentTabIndex重复为0,上一个页面做好拦截就好了!

在HarmonyOS Next中,Tabs组件的onChange事件触发后,currentTabIndex被重置为0,通常是因为事件处理中未正确更新状态或绑定的数据源。检查Tabs组件的currentIndex属性是否与状态变量正确绑定,并确保在onChange回调中更新该状态变量。若状态管理不当,组件会恢复默认值0。

在 HarmonyOS Next 中,Tabs 组件的 onChange 事件触发后,currentTabIndex 被重置为 0,通常是由于状态管理与组件生命周期或事件触发顺序的冲突导致的。根据你提供的代码,问题可能出在以下两点:

  1. 状态更新与 TabsController.changeIndex 的循环触发
    你在 onChange 中调用了 handleTabChange,其中会执行 this.tabsController.changeIndex(index)
    如果 Tabs 组件本身已经通过 index 属性绑定了 currentTabIndex,再调用 changeIndex 可能会触发额外的状态重置或重新渲染,导致 currentTabIndex 被意外覆盖为初始值(0)。

  2. index 属性与 controller 的冲突
    Tabs 组件同时设置了 index={this.currentTabIndex}controller={this.tabsController}
    onChange 触发时,你通过 controller.changeIndex() 手动切换 Tab,这可能与 index 属性的双向绑定产生冲突,导致组件内部状态被重置。

建议修改方案
移除 onChange 中的 tabsController.changeIndex(index) 调用,因为 Tabs 组件在 index 属性绑定后会自动处理 Tab 切换。只需在 onChange 中更新 currentTabIndex 即可:

.onChange((index: number) => {
  console.log('change-index', index)
  if (index !== this.currentTabIndex) {
    this.currentTabIndex = index
    this.currentTabKey = TABBAR_LIST[index].key
  }
})

同时,确保 Tabsindex 属性正确绑定到 currentTabIndex,这样组件的选中状态会随状态变量自动同步。TabsController 通常用于主动控制 Tab 切换(例如通过代码触发切换),在响应式场景中可能不需要。

回到顶部