open harmony 项目实战:用 AppStorage 实现轻量级页面路由和状态管理

在 OpenHarmony 项目里,如果应用规模不是特别大,不一定一开始就要引入复杂路由方案。我的“语文视界”项目采用了一个更轻量的做法:用 AppStorage 记录当前页面、上一个页面和详情页参数,再由主入口 Index.ets 控制页面展示。✨

这篇文章就来拆解这种做法。

一、为什么要自己做轻量路由

语文学习 App 的页面层级大致是这样:

  • 首页、诗词、阅读、字典、学习、我的:一级页面。
  • 诗词详情、诗人详情、阅读详情:二级页面。
  • 收藏、反馈、推荐、诗词配对、默写、朝代排序:功能页。

如果每个页面都独立管理跳转,代码会比较散。我的做法是把跳转统一收敛到 Index.ets,让它成为页面调度中心。

二、核心状态设计

Index.ets 中最重要的是两个状态:

@State currentTabIndex: number = 0;
@State currentView: string = 'home';

currentTabIndex 负责底部导航选中状态,currentView 负责真正展示哪个页面。

进入页面时,还会从全局存储中恢复页面状态:

private checkSubPageNav(): void {
  const view = AppStorage.get<string>('current_view');
  if (view) {
    this.currentView = view;
  }
}

这样即使页面状态被其他模块写入,主容器也能同步更新。

三、页面跳转怎么写

以进入诗词详情为例:

private navToPoetryDetail(poetryId: number): void {
  AppStorage.setOrCreate('prev_view', this.currentView);
  AppStorage.setOrCreate('nav_poetry_id', poetryId);
  AppStorage.setOrCreate('current_view', 'poetry_detail');
  this.currentView = 'poetry_detail';
}

这段代码做了三件事:

  1. 保存上一页,用于返回。
  2. 保存诗词 id,用于详情页加载数据。
  3. 切换当前页面为 poetry_detail

阅读详情也是类似:

private navToReadingDetail(id: number): void {
  AppStorage.setOrCreate('prev_view', this.currentView);
  AppStorage.setOrCreate('nav_reading_id', id);
  AppStorage.setOrCreate('current_view', 'reading_detail');
  this.currentView = 'reading_detail';
}

四、详情页如何接收参数

诗词详情页通过 AppStorage 获取 nav_poetry_id

aboutToAppear(): void {
  const poetryId = AppStorage.get<number>('nav_poetry_id');
  if (poetryId !== undefined && poetryId > 0) {
    this.poetryId = poetryId;
    this.loadPoetryDetail();
  }
}

阅读详情页也是同样思路:

const raw = AppStorage.get<number>('nav_reading_id');
if (raw && raw > 0) {
  this.readingId = raw;
  this.item = getReadingItemById(raw);
}

这很像一个极简参数传递机制,适合本项目这种页面关系清晰的应用。

五、返回逻辑

返回时只需要读取 prev_view

private goBack(): void {
  const prevView = AppStorage.get<string>('prev_view') || 'home';
  this.currentView = prevView;
  AppStorage.setOrCreate('current_view', prevView);
}

这个实现很简洁。不过也有一个注意点:如果未来页面层级更深,只存一个 prev_view 可能不够,需要升级成页面栈。

六、页面渲染逻辑

Index.ets 里根据 currentView 决定展示哪个页面:

if (this.currentView === 'poetry_detail') {
  PoetryDetail({ onBack: () => this.goBack() });
} else if (this.currentView === 'reading_detail') {
  ReadingDetail({ onBack: () => this.goBack() });
} else if (this.currentView === 'poetry_list') {
  PoetryList({
    onPoetryClick: (id: number) => this.navToPoetryDetail(id)
  });
}

这种写法的优点是页面关系很直观。打开文件就能看到整个应用的页面流转关系。

七、Tab 切换时的动画

切换底部 Tab 时,项目还加入了淡出和滑动动画:

animateTo({
  duration: ANIM_DURATION.FAST,
  curve: ANIM_CURVES.STANDARD,
  onFinish: () => {
    this.currentTabIndex = index;
    this.currentView = viewMap[index] || 'home';
  }
}, () => {
  this.tabContentOpacity = 0;
  this.tabContentTranslateY = -5;
});

页面状态切换不只是“换内容”,还带有轻微过渡,体验会顺滑很多。😊

八、这种方案适合什么场景

适合:

  • 页面数量中等。
  • 页面层级不深。
  • 参数传递简单。
  • 不需要复杂路由守卫。
  • 想快速完成项目闭环。

不太适合:

  • 页面栈很深。
  • 需要复杂权限控制。
  • 页面跳转来源很多。
  • 需要 URL 化或强路由表管理。

九、可以继续优化的方向

如果项目继续做大,可以考虑:

  • current_view 定义成枚举或常量,避免字符串写错。
  • 把跳转方法封装成 NavigationService
  • prev_view 升级为页面栈。
  • 为详情页参数增加类型约束。

总结

AppStorage 不只是用来保存简单状态,也可以在中小型 OpenHarmony 项目中承担轻量页面路由的职责。

在“语文视界”里,它让首页、详情页、学习页、收藏页之间的跳转变得清晰可控。对于刚开始做 OpenHarmony 项目的同学来说,这是一种非常容易理解、也很实用的方案。🌟

img

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐