欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

各位伙伴,我是Moranbika。我们一同走过了紧张而充实的第二阶段(DAY8-DAY13),成功将一个单页面的“功能模块”,进化为一个拥有底部导航、多个页面的“应用骨架”。如果说第一阶段是“筑基”,那么第二阶段就是“搭梁”。在DAY14这个复盘日,我们的目标不是庆祝功能完成,而是要完成一次认知的跃迁:从“如何实现一个功能”转向“如何设计一个可持续扩展的架构”

复盘的目的,是让我们在未来的项目中,能系统性地规避问题,复用成功模式。今天,我将以我的第二阶段实践为例,带你进行一次从技术细节到写作表达的全面“精修”。

第一部分:审视成果与定位问题——复盘从“清点”开始

首先,让我们明确第二阶段我们究竟交付了什么:

  1. 一个自定义的、双向状态绑定的底部导航组件(CustomTabBar

  2. 一个基于原生 Tabs 和 @ohos.router 的导航控制中枢(MainPage

  3. 四个独立的功能页面(Home, List, Profile, Settings),并解决了它们的状态保持问题。

  4. 一套初步的多终端UI适配策略

接下来,对照训练营的“发文规则”这面镜子,审视初版博文最容易出现的三类典型问题:

  • 问题A(流水账):“我创建了四个页面文件,然后在主页用if/else把它们包起来,最后下面放了个Row里面四个Column做TabBar。”

  • 问题B(浅尝辄止):“页面切换会丢失状态,我用了@StorageLink存起来就好了。”

  • 问题C(结构散乱):文章从头到尾一个标题,像一篇没有段落的小说。

我们的优化,就是要彻底消灭这些问题。

第二部分:规则合规性优化——剔除无效,注入深度

我们需要像修剪枝叶一样,剪掉无价值的叙述,让主干(技术决策和问题解决)更加突出。

1. 删除“功能清单”,增加“决策分析”

  • 优化前(应删除):“首先,我规划了四个Tab:首页、列表、我的、设置。然后在DevEco Studio里右键新建了四个.ets文件,分别取名HomePage, ListPage...”

  • 优化后(应强化)

    导航架构的核心决策:状态驱动 vs 事件驱动

    在实现底部导航时,我面临一个关键架构选择:是让每个Tab按钮直接触发页面跳转(事件驱动),还是让Tab按钮只改变一个核心状态,再由这个状态驱动页面变化(状态驱动)?

    方案对比与抉择:

    • 事件驱动TabBar组件内直接调用router.pushUrl弊端是导航逻辑散落在UI组件中,TabBar与页面高度耦合,极难测试和复用。

    • 状态驱动TabBar只通过@Link修改父组件的currentIndex状态,由MainPage监听此状态并控制Tabs组件或执行路由。优势是逻辑清晰、职责分离、状态集中管理。

    我选择了状态驱动。这不仅是实现一个功能,更是采用了更符合声明式UI范式的数据流思想。CustomTabBar因此成为一个纯净的、“愚蠢”的展示组件,它只负责接收currentIndextabItems并渲染,这为未来的UI换肤和动态Tab配置打下了坚实基础。

2. 将“解决方案”升级为“解决方案评估矩阵”
对于“页面状态丢失”这一核心痛点,不能只提一种方法。

  • 优化前(不完整):“我用AppStorage解决了状态保持问题。”

  • 优化后(体系化)

    挑战:多Tab切换下的页面状态保持

    Tabs组件内切换非相邻页面时,中间页面的组件实例会被销毁,导致滚动位置、表单内容等状态丢失。

    我探索并评估了三种主流方案:

    方案 实现方式 优点 缺点 适用场景
    状态持久化 使用@StorageLinkAppStorage将状态提升至应用级。 可靠、通用,状态可跨页面共享。 需要手动管理存储键名,数据模型复杂时稍显繁琐。 推荐。大多数需要持久化状态的场景,如列表滚动位、未提交的表单。
    组件常驻 使用if/else条件渲染替代Tabs,所有页面实例常驻内存。 实现简单,状态绝对不丢失。 内存开销大,页面生命周期管理失效。 页面数量少、组件轻量、且对内存不敏感的场景。
    增加缓存 设置TabscachedCount属性为页面数量。 配置简单,原生支持。 官方警告可能影响性能,属于“黑盒”配置。 作为前两种方案的辅助,小幅度提升体验。

    我的综合策略:对于ListPage的滚动位置,采用方案一(@StorageLink)进行精准持久化。对于整个应用的Tab索引,也采用方案一,确保应用重启后能回到上次的Tab。这体现了‘根据状态类型和数据生命周期选择最适方案’的设计原则。

第三部分:导师意见落地与技术深度升级

假设导师审阅后提出:“对@Link@StorageLink的使用场景区别可以讲得更透。” 这不能简单加一句话应付。

优化记录与深化分析:

【导师意见落地】:区分@Link@StorageLink的应用场景。

原内容:在CustomTabBar中使用了@Link currentIndex,在ListPage中使用了@StorageLink scrollOffset

深度解析与修正
这两个装饰器的选择,精确反映了我对数据流和状态生命周期的设计意图。

  1. @Link 用于组件间的“实时状态同步”

    • 场景MainPageCustomTabBar需要共享并同步currentIndex。这个状态只在当前页面会话中有意义,不需要持久化,也不需要让其他无关页面访问。

    • 机制:它建立了一个从父组件(MainPage)到子组件(CustomTabBar)的双向数据绑定。任何一方的修改都会立即同步到另一方,且仅在此组件树范围内生效。

    • 类比:就像两个人面对面合作编辑一份纸质文档,改动即时可见,但文档不离开会议室。

  2. @StorageLink 用于应用级的“状态持久化与跨页面共享”

    • 场景ListPage的滚动位置需要被记住,即使用户退出应用再打开,或从其他Tab切回来,都应恢复。

    • 机制:它将状态存入一个全局的、可持续化的存储池(AppStorage)。任何绑定此键名的组件,无论其在组件树的何处,都能读取和修改这个状态,修改会全局同步。

    • 类比:将文档上传到云端网盘,任何有链接的设备在任何时间点都能访问和编辑最新版本。

总结:选择@Link是为了解耦UI组件并保持状态同步,选择@StorageLink是为了超越组件生命周期持久化状态。这个微小的选择,背后是对ArkUI状态管理框架的深刻理解。

第四部分:内容质量的结构化与佐证升级

1. 结构化呈现:为文章搭建清晰骨架
一篇好的技术文章应该像一本好书,有目录和章节。优化后的文章结构大纲如下:

【第二阶段】构建开源鸿蒙应用的导航骨架:架构、实现与优化

一、引言:从单页面到多页面应用的挑战
二、架构设计:导航模式选型与信息结构
2.1 原生路由 vs 三方导航库的抉择
2.2 定义我们的四模块信息架构
三、核心实现:状态驱动的自定义导航系统
3.1 构建数据模型与纯净的CustomTabBar组件
3.2 主页面(MainPage):状态中枢与Tabs控制器
3.3 关键技术:详解@Link的双向绑定机制
四、攻坚实录:解决页面状态丢失的三大战役
4.1 问题现象:切换Tab后,列表为何总回顶部?
4.2 方案探析:状态持久化、组件常驻、缓存优化的对比实验
4.3 最终方案:基于@StorageLink的精准状态恢复策略
五、进阶适配:应对多终端与开发板的布局挑战
六、总结:第二阶段的架构思维收获
附录:关键代码片段与Git提交记录

2. 佐证性升级:让逻辑拥有坚实的证据

  • 必备证据:应用在手机横竖屏、平板、开发板(DAYU200)上运行的截图,清晰展示导航栏在不同设备上的适配效果。

  • 过程证据:提供Tabs组件在cachedCount设为不同值时的内存占用Profiler工具截图对比,用数据支撑你的性能决策。

  • 代码证据:在讲解@Link时,附上MainPage中 CustomTabBar({ currentIndex: $currentTabIndex }) 的调用代码,并注释 $ 符号是@Link双向绑定的语法糖,这能极大帮助新手理解。

第五部分:一致性校验与知识体系串联

最后,站在更高的视角,审视并连接你的知识版图。

1. 术语一致性检查

  • 确保在所有文章中,始终使用“Tabs组件”而非“那个切换器”,使用“状态驱动”而非“用数据控制”。

  • 统一“页面”(Page)和“组件”(Component)的称呼,ArkUI中万物皆组件,但我们常将入口组件称为页面。

2. 跨阶段知识串联

  • 在第二阶段讲到ListPage时,应关联第一阶段DAY4-DAY6的成果:“此ListPage完整集成了第一阶段实现的网络列表、下拉刷新与上拉加载功能。”

  • 在讲解多终端适配时,可以呼应DAY2的多端运行环境:“正是基于DAY2在真机、开发板、模拟器上建立的完整调试能力,本阶段的UI适配工作才能高效验证。”

第二阶段核心知识体系提炼

  • 架构层:状态驱动设计、组件通信模型(@Link@Provide/@Consume)、导航架构模式。

  • 组件层:容器组件(TabsScroll)的深度使用、自定义复合组件的设计与封装原则。

  • 状态管理层:局部状态(@State)、组件间状态(@Link)、应用全局状态(@StorageLink/AppStorage)的精准运用场景。

  • 适配层:响应式布局初步、基于窗口变化的布局调整。

  • 工程层:多页面代码组织、模块化思维。

最终提交:为第二阶段画上圆满句号

bash

git add .
git commit -m “docs: 完成第二阶段(DAY8-DAY13)深度复盘与博文优化

- 重构内容核心,剔除所有实现步骤罗列,强化架构决策分析(状态驱动导航)
- 建立‘问题-方案评估矩阵’,系统化阐述解决状态保持等挑战的思考过程
- 深入解析@Link与@StorageLink的设计区别,回应导师意见并提升技术深度
- 重塑文章结构,采用技术方案书式的层级标题,增强可读性
- 补充多终端运行截图、性能对比图等关键佐证材料
- 校验并统一术语,明确串联第一阶段与第二阶段的知识点”

git push origin main

DAY14心法:复盘,是赋予工作以意义的过程。通过今天的梳理,第二阶段的经历不再是零散的代码记忆,而是内化为一套清晰的架构决策方法论问题解决工具箱。你不仅优化了几篇文章,更是优化了未来面对复杂功能时的思考路径。现在,带着这个更强大的思维框架,让我们满怀信心地进入第三阶段——动效与用户体验的深水区

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐