鸿蒙基础复盘生命周期、启动链路、路由跳转与真实需求定位一、为什么要复盘这一轮前面已经完成了两个 UI 卡片组件AI 总结卡片和 AI 问题走马灯卡片。组件层面主要练习了ComponentV2、Param、Event、ObservedV2、Trace、Swiper和TouchEvent。这一轮继续往项目基础走重点复习1. 组件生命周期 2. Ability 启动链路 3. 路由跳转与页面传参 4. 真实需求代码定位流程 5. 最小改动原则 6. 数据没出来时的排查顺序这些内容比单纯写 UI 更接近真实业务开发因为做需求时不只是把组件画出来还要知道页面从哪里来、什么时候加载、数据在哪里准备、事件往哪里传。二、组件生命周期ArkUI 自定义组件中常用生命周期包括aboutToAppear() build() aboutToDisappear()1. aboutToAppear()aboutToAppear()是自定义组件实例创建后、build()执行前调用的生命周期。执行顺序可以理解为创建组件实例 ↓ aboutToAppear() ↓ build() ↓ UI 渲染它适合做1. 初始化组件状态 2. 调用 Controller 加载数据 3. 注册监听 4. 启动和当前组件展示相关的逻辑例如aboutToAppear():void{this.controller.aboutToAppear()}这种写法表示组件即将出现时把初始化逻辑交给 Controller。2. build()build()是组件 UI 的声明入口主要负责写 UI 结构和样式。它适合写1. Row / Column / Stack 等布局 2. Text / Image / Swiper 等组件 3. 简单条件渲染 4. 样式声明不适合写1. 接口请求 2. 复杂业务判断 3. 路由跳转 4. 定时器创建 5. 大量数据处理3. aboutToDisappear()aboutToDisappear()是组件即将销毁、从组件树中移除前调用的生命周期。它适合清理1. setInterval 2. setTimeout 3. 页面监听 4. 事件订阅 5. 轮询任务 6. 动画任务 7. 长连接或资源占用如果组件里有定时器但不清理可能导致1. 页面离开后定时器仍然执行 2. 多次进入页面后叠加多个定时器 3. 重复请求接口 4. 重复刷新状态 5. 页面卡顿 6. 内存泄漏 7. 动画速度异常三、应用启动链路一个鸿蒙应用不是直接从业务首页开始执行而是有完整启动链路module.json5 ↓ EntryAbility.ets ↓ onCreate() ↓ onWindowStageCreate() ↓ windowStage.loadContent(pages/MainPage) ↓ MainPage.ets ↓ 导航容器 / 路由容器 ↓ 业务首页1. module.json5module.json5是模块配置文件不是依赖文件。它通常配置1. 当前模块信息 2. Ability 信息 3. srcEntry 入口文件 4. pages 配置 5. 权限 6. metadata系统启动应用时会根据这里的配置找到 Ability 入口文件。2. EntryAbility.etsEntryAbility.ets是 UIAbility 的实现文件是当前模块配置的 Ability 启动入口。它不是普通页面也不是业务首页而是应用能力入口。它通常包含onCreate() onWindowStageCreate() onForeground() onBackground() onDestroy()3. onCreate()onCreate()在 UIAbility 创建时执行适合做 Ability 级别初始化例如1. 初始化日志 2. 初始化路由 3. 初始化全局配置 4. 初始化 SDK 5. 读取启动参数4. onWindowStageCreate()onWindowStageCreate()在窗口舞台创建后执行通常在这里加载根页面onWindowStageCreate(windowStage:window.WindowStage):void{windowStage.loadContent(pages/MainPage)}5. windowStage.loadContent()windowStage.loadContent(pages/MainPage)的作用是加载指定路径下的页面组件作为当前窗口内容。它本身不一定就是业务首页。loadContent 只负责加载 MainPage。 MainPage 是不是业务首页要看 MainPage.ets 的具体实现。如果 MainPage 里面写的是导航容器那么 MainPage 就负责承接后续路由页面。四、为什么业务首页不直接写在 EntryAbility 中真实项目中通常不会把首页 UI 直接写在EntryAbility中因为它们职责不同EntryAbility 负责应用生命周期和窗口加载。 MainPage 负责承接页面容器或导航容器。 路由系统 负责页面栈管理、跳转、传参、拦截器、动画等。 业务首页 负责具体 UI 和业务逻辑。这样做的好处1. 启动逻辑和业务 UI 解耦 2. 路由统一管理 3. 方便切换首页、登录页、引导页 4. 方便接入拦截器和页面生命周期监听 5. 多业务模块可以通过路由注册接入 6. EntryAbility 保持简洁五、路由封装与页面常量真实项目通常会封装路由跳转方法例如HMUtil.push({pageUrl:PageConstant.AgentChatPage,param:{question:question,autoSend:true}})封装路由的好处1. 统一跳转入口 2. 降低业务代码和底层路由库耦合 3. 后续路由库变更时只改封装层 4. 可以统一加日志、埋点、异常处理、拦截器 5. 调用处代码更简洁页面路径也不建议直接写字符串pageUrl:pages/AgentChatPage更推荐使用常量pageUrl:PageConstant.AgentChatPage好处是1. 避免拼写错误 2. 路由地址统一管理 3. 后续改路径只改常量 4. 全局搜索更方便 5. 可以快速知道项目有哪些页面路由六、页面传参应该由谁组装页面跳转参数更推荐由 Controller 组装而不是 UI 组件直接组装。推荐链路子组件点击 ↓ Event 抛出必要数据 ↓ 父组件调用 Controller 方法 ↓ Controller 组装路由参数 ↓ Controller 调用 HMUtil.push 跳转示例AiQuestionCard({onQuestionClick:(question:string){this.controller.jumpAgentWithQuestion(question)}})Controller 中publicjumpAgentWithQuestion(question:string):void{HMUtil.push({pageUrl:PageConstant.AgentChatPage,param:{question:question,source:ai_question_card,autoSend:true}})}这样可以避免 UI 组件和具体业务路由强绑定。七、目标页面在哪里接收参数目标页面应该在页面入口层、Controller 初始化阶段或页面级生命周期中统一接收路由参数。不建议在普通 UI Builder 中到处取参数因为1. 参数读取分散后续不好查 2. build / Builder 应该偏 UI 3. 多处读取容易重复 4. 参数校验、默认值处理应该集中管理 5. 自动行为应该避免重复触发示例aboutToAppear():void{this.controller.initRouteParam()}Controller 中publicinitRouteParam():void{constparamgetCurrentParam()asAgentPageParam|undefinedthis.viewModel.questionparam?.question??}八、点击问题进入 AI 页面并自动发送的完整链路完整链路可以设计成1. 用户点击问题气泡。 2. Card 组件触发 onQuestionClick(question)。 3. 父组件接收到 question调用 Controller。 4. Controller 组装路由参数 question、source、autoSend。 5. Controller 调用 HMUtil.push 跳转 Agent 页面。 6. Agent 页面在页面级初始化阶段接收路由参数。 7. AgentController 校验参数 question 是否为空、autoSend 是否为 true、是否已自动发送过。 8. 将 question 填入输入状态或直接构造用户消息。 9. 调用统一发送方法 sendMessage(question)。 10. sendMessage 内部添加用户消息、AI loading、发起请求、更新回复、结束 loading。这里要特别注意自动发送要防止重复触发。privatehasAutoSend:booleanfalsepublictryAutoSendQuestion(question?:string,autoSend?:boolean):void{if(this.hasAutoSend){return}if(!autoSend||!question){return}this.hasAutoSendtruethis.sendMessage(question)}九、拿到真实需求后如何定位代码拿到一个页面需求后不要一看到截图就直接改 UI。推荐流程1. 看需求截图和文案找页面上的唯一关键词。 2. 全局搜索文案定位可能的 UI 文件。 3. 如果搜不到文案就从已知入口页面开始看点击事件。 4. 顺着 onClick / controller 方法找到跳转逻辑。 5. 根据 pageUrl / 路由常量找到目标页面。 6. 进入目标页面后看状态分支比如 HISTORY / SUGGEST / RESULT。 7. 定位真正渲染需求区域的组件。 8. 再看数据来源ViewModel、Controller、Biz、接口。截图只能告诉你页面长什么样不能告诉你代码落点。真实项目可能有多个状态、多个入口、多个复用组件所以必须先确认路由、状态分支、数据来源和真实组件。十、最小改动原则最小改动原则可以理解为尽量沿用项目原有结构、封装方法和分层方式只改需求影响范围内的代码。具体包括1. 不随便改启动入口 2. 不重复注册已有路由 3. 不绕过项目封装工具类 4. 不把业务逻辑塞进 UI 5. 不为了一个需求大范围重构 6. 优先复用已有 Controller、ViewModel、Biz、路由常量 7. 只改需求相关的最小范围代码一句话先顺着项目原有架构加功能不要为了功能跑通而破坏架构。十一、什么时候新建组件什么时候用 Builder适合新建组件1. UI 模块比较完整 2. 有独立业务含义 3. 后续可能复用 4. 代码量比较多 5. 有自己的参数和事件 6. 可以独立维护样式适合Builder1. 只是当前组件内部的一小段 UI 2. 不需要跨文件复用 3. 只是为了拆分 build 结构 4. 依赖当前组件内部状态较多一句话完整模块新建组件。 组件内部 UI 片段用 Builder。十二、UI 改完后数据没出来怎么排查推荐排查顺序1. 先看组件有没有挂载 - 背景出来了吗 - 按钮出来了吗 - 临时 Text(测试) 能显示吗 2. 看父组件有没有传参 - topQuestionList 是否有值 - bottomQuestionList 是否有值 3. 看 ViewModel 状态有没有值 - Trace 字段是否赋值 - 字段名有没有传错 4. 看 Controller 有没有执行 - aboutToAppear 是否调用 - loadData 是否执行 - initRows 是否执行 5. 看 Biz / mock / 接口有没有返回 - then 是否进入 - catch 是否报错 - 返回数组是否为空 6. 看数据是否被格式化过滤掉 - 长度限制是不是太严格 - trim 后是不是空字符串 - slice 后是不是变空 7. 看 UI 渲染条件 - if 条件是否挡住 - ForEach 的数组是不是空 - key 是否异常如果背景和按钮出来了但问题气泡没出来说明组件已经挂载问题更可能在数组为空、父组件没传参或 ViewModel 没赋值。十三、本轮总结这一轮把三条线串起来了组件生命周期 aboutToAppear / build / aboutToDisappear 应用启动链路 module.json5 - EntryAbility - onCreate - onWindowStageCreate - loadContent - MainPage 真实开发流程 文案定位 - 点击事件 - 路由常量 - 页面状态 - 组件 - ViewModel - Controller - Biz对鸿蒙实习开发来说真正重要的不只是会写 UI而是要知道页面怎么启动 组件什么时候初始化 数据从哪里来 事件往哪里传 跳转参数由谁组装 页面参数在哪里接收 出现问题该从哪一层排查这些内容掌握以后做真实业务需求会更稳。参考链接UIAbility 生命周期https://developer.huawei.com/consumer/cn/doc/HarmonyOS-Guides/uiability-lifecycle自定义组件生命周期https://developer.huawei.com/consumer/cn/doc/HarmonyOS-Guides/arkts-page-custom-components-lifecycle自定义组件https://developer.huawei.com/consumer/cn/doc/HarmonyOS-Guides/arkts-create-custom-componentsNavigation / NavDestinationhttps://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-navigation-navdestinationSwiper 组件https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-swiper触摸事件https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-events-touch