HarmonyOS 鸿蒙Next中Tabs作导航时,标签页的生命周期是?

HarmonyOS 鸿蒙Next中Tabs作导航时,标签页的生命周期是?

采用的是 API15,使用 Tabs 作底部导航栏时,对应内容在 TabContent 中,那么生命周期是怎么触发的? 我的登录业务将 user 相关信息存到 AppStorage 中了,而在好友分组页面中用 @StorageLink(‘user’) 拿到用户信息,然后在 aboutToAppear 和 onAppear 都试过了调接口获取该用户的好友分组列表,为什么登录后在好友分组页面并没有成功走到 aboutToAppear 或者 onAppear 中的逻辑,生命周期根本就没有触发啊?

// Layout
import { FriendPage } from './FriendPage';
import { HomePage } from './HomePage';
import { Mine } from './Mine';
import { PostPage } from './PostPage';
import { AppStorageV2, Font } from '@kit.ArkUI';
import { User } from '../module/user';

@Builder
export function LayoutBuilder() {
  Layout();
}

@Component
struct Layout {
  private tabsController: TabsController = new TabsController();
  @State currentIndex: number = 0;
  pathStack: NavPathStack = AppStorageV2.connect(NavPathStack, 'navStack',() => new NavPathStack())!
  font: Font = new Font();
  [@StorageLink](/user/StorageLink)('user')
  user: User | undefined = AppStorage.get('user')

  aboutToAppear(): void {
    // 注册字体
    this.font.registerFont({
      familyName: '阿里汉仪智能黑体',
      familySrc: $rawfile('fonts/阿里汉仪智能黑体.ttf')
    })
    if(!this.user){
      this.pathStack.pushPathByName("Login", null, true);
    }
  }

  @Builder
  tabBarBuilder(title: string, targetIndex: number, selectedIcon: Resource, unselectIcon: Resource) {
    Column({ space: 5 }) {
      Image(this.currentIndex === targetIndex ? selectedIcon : unselectIcon)
        .width(24)
      Text(title)
        .fontFamily('阿里汉仪智能黑体')
        .fontSize(14)
        .fontColor(this.currentIndex === targetIndex ? '#0A59F7' : '#63AAAA')
        .textAlign(TextAlign.Center)
        .fontWeight(500)
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
    .onClick(() => {
      this.currentIndex = targetIndex;
      this.tabsController.changeIndex(targetIndex)
    })
  }

  build() {
    NavDestination() {
      Tabs({ barPosition: BarPosition.End, controller: this.tabsController }) {

        TabContent() {
          HomePage()
        }
        .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
        .backgroundColor('#F6F6F6')
        .tabBar(this.tabBarBuilder('主页', 0, $r('app.media.home_blue_selected'), $r('app.media.home')))

        TabContent() {
          PostPage()
        }
        .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
        .backgroundColor('#F6F6F6')
        .tabBar(this.tabBarBuilder('动态', 1, $r('app.media.post_blue_selected'), $r('app.media.post')))

        TabContent() {
          FriendPage()
        }
        .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
        .backgroundColor('#F6F6F6')
        .tabBar(this.tabBarBuilder('好友', 2, $r('app.media.friends_blue_selected'), $r('app.media.friends')))

        TabContent() {
          Mine()
        }
        .backgroundColor('#F6F6F6')
        .tabBar(this.tabBarBuilder('我的', 3, $r('app.media.mine_blue_selected'), $r('app.media.mine')))
        .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
      }
      .divider({
        strokeWidth: '2vp',
        color: Color.Gray,
      })
      .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
      .scrollable(false)
      .vertical(false)
    }
    .onReady((context: NavDestinationContext) => {
      this.pathStack = context.pathStack;
    })
  }
}
// 好友分组页
import { Friend } from "../network/interface/friend";
import { getFriendCategoriesApi } from "../network/api/friend"
import { AppStorageV2, PromptAction } from "@kit.ArkUI"
import { User } from "../module/user";

@Component
export struct FriendPage {
  pathStack: NavPathStack = AppStorageV2.connect(NavPathStack, 'navStack', () => new NavPathStack())!
  private tabsController: TabsController = new TabsController();
  toast: PromptAction = new PromptAction()
  @State
  categoryList: Friend.ResFriendCategories[] = []
  getCategories = async () => {
    try {
      const res = await getFriendCategoriesApi()
      this.categoryList = res.data
      console.log('====================好友分组列表:', res.data)
    } catch (e) {
      this.toast.showToast({
        message: '获取好友分组列表失败',
        duration: 2000,
      })
      console.log(e)
    }
  }

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

  [@StorageLink](/user/StorageLink)('user')
  user: User | undefined = AppStorage.get('user')

  build() {
    Column({ space: 5 }) {
      // 搜索区域
      Row() {
        Image($r('app.media.ic_search'))
          .width(22)
          .fillColor('#817D83')
        TextInput({ placeholder: '搜索好友...' })
          .backgroundColor(Color.Transparent)
          .placeholderColor('#817D83')
          .padding({ left: 5 })
          // 除去别的宽度,剩余的给 TextInput
          .layoutWeight(1)
          .fontColor('#999')
        // Image($r('app.media.ic_code'))
        //   .width(20)
        //   .fillColor('#817D83')
      }
      .backgroundColor('#E9E9E9')
      .width('100%')
      .border({ radius: 20 })
      .padding({ left: 8, right: 8 })

      Tabs({ barPosition: BarPosition.Start, controller: this.tabsController }) {
        TabContent() {
          Text('Tab1')
        }
        .tabBar(SubTabBarStyle.of('全部好友'))

        ForEach(this.categoryList, (item: Friend.ResFriendCategories) => {
          TabContent() {
            Text("分组id:" + item.pkId)
          }
          .tabBar(SubTabBarStyle.of(item.name))
        }, (item: Friend.ResFriendCategories) => item.pkId.toString())
      }
      .scrollable(true)
      .vertical(false)
    }
    .width('100%')
    .height('100%')
    .padding({
      left: 10,
      right: 10,
      top: 5,
      bottom: 5
    })
  }
}

更多关于HarmonyOS 鸿蒙Next中Tabs作导航时,标签页的生命周期是?的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

在HarmonyOS Next中,Tabs作为导航时,标签页生命周期如下:

  1. 首次加载时触发aboutToAppear
  2. 离开当前标签页时触发aboutToDisappear
  3. 返回标签页时再次触发aboutToAppear
  4. 组件销毁时触发aboutToDisappear

非当前显示的标签页会被保留在内存中,不会重复创建。页面状态保持由ArkUI框架自动管理,切换标签页不会触发页面重建。

更多关于HarmonyOS 鸿蒙Next中Tabs作导航时,标签页的生命周期是?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,Tabs组件作为导航时,TabContent的生命周期触发机制如下:

  1. 首次加载时,默认显示的TabContent会触发aboutToAppear和onAppear生命周期
  2. 切换Tab时:
    • 新显示的TabContent会触发aboutToAppear和onAppear
    • 被隐藏的TabContent会触发onDisappear
    • 但不会销毁隐藏的TabContent,只是将其移出视图

根据你的代码分析,问题可能出在:

  1. FriendPage可能不是初始显示的TabContent,所以首次登录时不会触发其生命周期
  2. 建议在FriendPage中添加onPageShow回调来监听页面显示事件:
onPageShow() {
  this.getCategories()
}
  1. 或者使用Tabs的onChangeIndex事件来主动触发数据加载:
Tabs({
  onChangeIndex: (index: number) => {
    if(index === 2) { // 好友页的索引
      this.getCategories()
    }
  }
})
  1. 确保AppStorage中的user数据变更能正确触发@StorageLink的更新

这种设计是为了优化性能,避免不必要的资源消耗。只有当前显示的TabContent会保持活跃状态。

回到顶部