羽毛球教程 HarmonyOS 学习应用(01):学习、收藏与我的三栏架构

发布时间:2026/7/26 14:46:15
羽毛球教程 HarmonyOS 学习应用(01):学习、收藏与我的三栏架构 一、三栏的真实边界学习、收藏与我的羽毛球学习应用的主框架并不把每个功能都塞进底部导航。可高频切换、需要保留当前状态的三个顶层域固定为“学习、收藏、我的”课程详情、搜索、练习记录、学习进度和测验等页面则从对应顶层域继续进入。这种划分首先解决信息架构问题学习页负责内容发现与进度入口收藏页承接用户主动保存的课程我的页面汇总个人数据与工具入口。练习记录虽然重要但它是个人学习数据的一部分不应与三个顶层域争夺常驻位置。顶层域主要内容保留的状态继续进入的页面学习模块、搜索、课程进度当前模块和学习统计分类、详情、测验、进度收藏已收藏课程收藏集合课程详情我的个人资料与工具账号展示、主题、统计练习记录、笔记、设置二、TabDef 让文案、标识和顺序只定义一次主框架先用一个小模型描述三个入口。手机底栏和平板侧栏都遍历同一个TABS因此不会出现手机端叫“收藏”、平板端却叫“练习”的分叉。interface TabDef { id: string label: string emoji: string } type TabId home | favorite | profile const TABS: TabDef[] [ { id: home, label: 学习, emoji: }, { id: favorite, label: 收藏, emoji: ❤ }, { id: profile, label: 我的, emoji: } ] const DEFAULT_TAB: TabId home function isTabId(value: string): value is TabId { return TABS.some(tab tab.id value) }id是稳定业务身份label和emoji只是展示属性。后续若替换为 Symbol 或资源图标只需改变显示字段不必改动页面切换条件。状态字段直接驱动界面刷新的规则可对照华为官方的 State 状态管理说明这里使用应用级链接状态是因为同一入口需要被不同布局共同读取。三、active_tab 是手机和平板共享的单一状态当前入口通过StorageLink(active_tab)连接到应用级状态。点击任意导航项只修改这个字符串页面内容和选中样式都直接读取它。StorageLink(active_tab) activeTab: string home private selectTab(tabId: string): void { this.activeTab tabId } // 导航项 .onClick(() this.selectTab(t.id))这比为三个按钮分别维护homeSelected、favoriteSelected、profileSelected更安全。单一值天然排除了“两个入口同时高亮”或“内容切换了但导航没切换”的非法组合。四、手机底栏只负责切换顶层内容小屏布局采用纵向结构内容区占据剩余高度底栏保持固定。内容判断和选中颜色都绑定到activeTab不依赖缓存的页面对象。Column() { Column() { if (this.activeTab home) { HomePage() } else if (this.activeTab favorite) { FavoritePage() } else { ProfilePage() } } .layoutWeight(1) .width(100%) this.bottomTabs() }底栏使用稳定的t.id作为ForEach键。列表顺序没有变化时ArkUI 可以复用导航项状态变化只更新颜色、字重和当前内容。五、平板侧栏复用状态不复制业务断点为小屏时渲染底栏其余断点切换为 220 vp 侧栏。两种布局只改变导航位置页面组件与状态源保持一致。StorageProp(breakpoint) breakpoint: Breakpoint sm build() { if (this.breakpoint sm) { this.phoneLayout() } else { this.tabletLayout() } } // 侧栏仍然使用同一个 activeTab .backgroundColor( this.activeTab t.id ? this.palette.badgeBg : Color.Transparent )这类响应式实现的关键不是“做两套页面”而是保持状态合同不变。窗口变宽时用户仍停留在原来的学习、收藏或我的页面不需要重新导航。六、顶层切换与路由跳转不能混为一层三栏切换适合高频、对等、可保留状态的顶层内容详情页则需要参数、返回栈与明确的生命周期应使用路由跳转。两者职责如下动作状态载体返回行为适用范围切换三栏active_tab再次点击即可切回顶层学习域打开课程详情路由参数courseId返回原列表单个课程打开测验路由参数moduleId返回模块模块内任务打开练习编辑可选logId返回记录列表新增或编辑如果把详情也做成 Tab返回栈、深层参数和状态恢复都会变得含糊如果把三个顶层入口全部做成路由频繁切换又会制造不必要的页面重建。七、异常状态要落在各自页面而不是主框架主框架只负责“显示哪个顶层域”。收藏为空、课程加载失败、资料字段缺失等问题由各页面自己渲染。这样一个页面的空状态不会让整个导航失效。导航层只需要守住三条边界1.activeTab只能取home、favorite、profile。 2. 未知值降级到“我的”之前应在初始化阶段归一化避免悄悄展示错误页面。 3. 断点变化只切换布局不能清空当前入口或用户数据。可以把允许值检查收敛到主框架入口避免持久化旧版本值或其他页面误写后进入不确定分支private normalizeTab(value: string): string { const allowed: string[] [ home, favorite, profile ] if (allowed.indexOf(value) 0) { return value } return home } aboutToAppear(): void { this.activeTab this.normalizeTab(this.activeTab) }降级到学习页比直接走最后一个else更明确未知值不会被误认为“我的”日志和测试也能准确定位是状态归一化触发而不是用户主动选择。八、从运行界面验证状态与布局手机运行界面可直接观察到三项结果底部标签为“学习、收藏、我的”学习入口高亮时首页模块和统计可见底栏固定在安全区域之上。验收还应覆盖以下路径1. 连续切换三个入口内容与高亮必须同步。 2. 从收藏进入课程详情再返回仍停留在收藏。 3. 从我的进入练习记录再返回仍停留在我的。 4. 调整窗口到平板断点导航改为侧栏但当前入口不变。 5. 切换深浅色主题选中态、分割线和文字仍可辨认。还要观察页面生命周期的副作用。切换 Tab 会重新进入对应组件时首页的当日学习标记应该去重收藏页不应重复装载同一集合我的页面也不应因为每次切回就追加统计。连续快速点击当前入口时界面保持稳定不创建额外路由记录应用恢复到前台后当前入口与主题状态仍与离开前一致。九、三栏架构的扩展规则新增功能时先判断它是否真的是与学习、收藏、我的对等的顶层域。只有高频、独立且需要常驻切换的内容才进入TABS课程工具、个人数据和一次性任务继续放在所属页面的路由下。这样导航数量不会随功能堆积手机和平板也能持续复用同一份状态。工程评审时可沿三条线检查数据线确认三个页面消费的共享状态没有被主框架复制交互线确认高亮、内容和返回位置只受一个入口值控制适配线确认断点只改变导航容器而不改变业务页面。三条线都成立后续替换图标、增加大字体或调整侧栏宽度才不会破坏顶层导航合同。