尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

HarmonyOS ArkTS API 24+ 实战:从机台卡片进入详情——稳定 ID、回调与页面状态

HarmonyOS ArkTS API 24+ 实战:从机台卡片进入详情——稳定 ID、回调与页面状态
📅 发布时间:2026/8/1 15:51:16

机台列表做出来以后,最容易出现的下一步需求就是“点哪台,就看哪台”。表面上只是给按钮加一个点击事件,实际却要先回答一个边界问题:卡片应该把整条机台数据交给页面容器,还是只交给一个稳定的标识?

本篇使用注塑工程师助手中的机台档案模块,梳理从MachineCard到MachineDetail的完整链路。它承接上一节的列表筛选,但不重复搜索和状态条件;重点放在machine.id、回调函数、页面容器状态,以及找不到对象时的降级界面。

一、列表页面不该自己决定详情页长什么样

机台列表位于entry/src/main/ets/features/machines/MachineArchive.ets。其中的MachineCard负责把编号、名称、状态、锁模力和位置组织成一张可扫读的卡片,也提供“查看详情”入口。

如果卡片在点击后直接拼装详情页,列表组件就要知道详情页的布局、返回动作和后续跳转。卡片职责会从“展示一条机台摘要”膨胀为“管理页面导航”,以后在产品页、报表页或异常页复用相同入口时,也会重复同一段跳转逻辑。

当前实现让卡片只发送一个机台 ID。页面容器决定要不要打开详情、打开哪一类详情,以及用户返回后如何回到原来的主页面。这种拆分让列表、路由状态和详情展示各自只有一个主要责任。

二、先认识机台模型中的稳定标识

机台模型位于entry/src/main/ets/models/Machine.ets。它同时保存展示字段和业务标识:

exportclassMachine{id:string;code:string;name:string;tonnage:number;location:string;status:MachineStatus;}

code是用户在页面上容易识别的设备编号,例如IM-120T-11;name用来描述设备用途。它们适合展示和搜索,但并不适合承担页面之间的唯一关联职责。编号规则可能调整,名称也可能修改;详情页若只依赖展示文案,就会把显示规则和关联规则绑在一起。

id的作用不同。它是数据层用于定位单个对象的稳定键。当前演示数据中第一台机台的 ID 是machine-001,详情页据此回到 Repository 查询完整对象。页面可以继续显示编号和名称,而关联链路不需要依赖这些可见文本。

三、卡片只上报 ID,不搬运整条对象

MachineCard对外暴露的回调参数是一个字符串:

@Componentstruct MachineCard{machine:Machine=newMachine('empty','','',0,'','idle');onOpen:(machineId:string)=>void=()=>{};}

按钮点击时,卡片把当前对象的id交给回调:

Button('查看详情').width('100%').height(34).onClick(()=>{this.onOpen(this.machine.id);})

这里没有把machine直接保存在详情页,也没有让卡片去修改外层页面状态。卡片只说明“用户希望打开 ID 为某值的机台”,至于怎样渲染、能否查到数据和返回到哪里,都留给拥有页面状态的上层组件处理。

这种选择还有一个实用好处:卡片里的对象可能来自筛选结果。上一节的关键词和状态条件会改变“当前显示哪些卡片”,却不应该改变“详情页根据 ID 查询哪台机台”的规则。传递稳定 ID 能让筛选结果与详情查询保持解耦。

四、列表组件把回调继续交给页面容器

MachineArchive本身不保存当前详情页状态,而是接收onOpenMachine:

@Componentexportstruct MachineArchive{onOpenMachine:(machineId:string)=>void=()=>{};onOpenProducts:()=>void=()=>{};}

在渲染列表时,它把这个回调传给每张卡片:

ForEach(this.filteredMachines(),(machine:Machine)=>{MachineCard({machine:machine,onOpen:this.onOpenMachine});},(machine:Machine)=>machine.id)

这段代码有两层含义。第一,ForEach使用machine.id作为稳定键,框架能据此区分不同卡片。第二,卡片点击后调用的仍然是外层提供的onOpenMachine,列表组件没有额外改写 ID,也不会偷换成编号或数组下标。

不要把数组下标当成详情参数。筛选、排序或刷新后,同一个下标可能对应另一台设备;详情页看上去能打开,却可能展示错误对象。ID 与下标的区别在列表比较简单时不明显,在过滤条件增加后就会变成难以追踪的问题。

五、页面容器保存“打开什么”和“打开谁”

应用入口页面位于entry/src/main/ets/pages/Index.ets。它维护两个状态:detailKind表示正在显示哪类详情,detailId表示这类详情要查询的对象。

@StatedetailKind:DetailKind='none';@StatedetailId:string='';privateopenDetail(kind:DetailKind,id:string):void{this.detailKind=kind;this.detailId=id;}privatecloseDetail():void{this.detailKind='none';this.detailId='';}

机台列表注入回调时,只需指定详情类型为machine:

MachineArchive({onOpenMachine:(machineId:string)=>this.openDetail('machine',machineId),onOpenProducts:()=>this.openDetail('productArchive','')})

这就是点击事件进入页面状态的关键一步。按钮发出machine-001,openDetail把页面切换到machine类型,同时把detailId保存为machine-001。因为这两个字段都属于响应式状态,页面会重新计算应该显示的组件。

六、详情组件只在对应状态下挂载

页面容器根据detailKind选择内容区域:

if(this.detailKind==='machine'){MachineDetail({machineId:this.detailId,onBack:()=>this.closeDetail(),onOpenProduct:(productId:string)=>this.openDetail('product',productId),onOpenDebug:(recordId:string)=>this.openDetail('debug',recordId)}).layoutWeight(1)}

MachineDetail收到的是 ID,不是列表卡片的实例。这样详情页可以独立查询机台数据,也能继续把产品 ID、调机记录 ID 等关联对象交回同一个页面容器。页面切换规则集中在Index.ets,不同详情页不需要彼此直接依赖。

从用户角度看,点击“查看详情”后,机台列表被详情内容替换;底部导航仍留在页面中。运行观察中,选择IM-120T-11后详情页显示相同的编号与名称,并展示锁模力、位置、状态、关联产品、调机记录和待处理异常。这些内容来自详情页按 ID 再次查询后的对象,而不是卡片临时拼接的文本。

七、详情页通过 Repository 重新定位对象

详情组件位于entry/src/main/ets/features/machines/MachineDetail.ets。它先检查 ID 是否存在,再取得当前机台:

privateexists():boolean{returndemoBusinessRepository.machineById(this.machineId)!==undefined;}privatecurrentMachine():Machine{constfound:Machine|undefined=demoBusinessRepository.machineById(this.machineId);returnfound===undefined?newMachine('missing','','',0,'','idle'):found;}

Repository 中的machineById使用同一个稳定键查找:

machineById(id:string):Machine|undefined{returnthis.machines.find((item:Machine)=>item.id===id);}

这条查询链路的好处是明确。列表负责发送 ID,页面容器负责保存 ID,详情页负责使用 ID 查询。读者沿着machineId搜索,就能从点击入口追到具体数据来源,而不用在多个组件里猜测对象何时被复制、何时失效。

八、找不到对象时不要继续渲染空数据

页面状态不一定永远有效。例如列表刷新后演示数据被恢复、未来接入数据同步后对象被删除,或者调用方传入了错误 ID。若详情页仍直接访问不存在对象的字段,用户通常看到空白内容或运行异常,而不是可以理解的提示。

当前组件先用exists()分支保护界面:

if(!this.exists()){Column({space:12}){Text('未找到机台档案')Text('该演示机台可能已被重置,请返回机台列表重新选择。')Button('返回机台列表').onClick(()=>this.onBack())}}else{// 渲染完整机台详情}

这是代码可直接推导出的降级路径:不存在的 ID 不会进入完整详情渲染,而会显示返回入口。当前普通列表只能传入现有机台 ID,因此缺失分支需要在受控状态下单独验证,不能把它误说成用户已通过正常点击必然看到的界面。

九、关联信息也从同一个 ID 出发

详情页中的关联产品、调机记录和异常计数,都通过当前机台的 ID 查询:

demoBusinessRepository.productsForMachine(this.currentMachine().id)this.debugRecords()demoBusinessRepository.openExceptionsForMachine(this.currentMachine().id)

这说明machine.id不只是“打开详情的参数”。它还是产品适用机台、调机记录、异常记录等关联关系的连接点。详情页不需要从列表卡片携带一份关联数据副本,而是围绕同一个 ID 按需读取各类数据。

需要注意的是,当前 Repository 使用本地脱敏演示数组。这能证明组件间的 ID 传递和查询边界,但不能证明已经完成服务端鉴权、远程同步、并发更新或真实产线设备接入。以后替换为网络数据源时,仍可保留 ID 回调和缺失态保护,同时补充加载、失败、请求竞态和权限处理。

十、四个常见错误与排查顺序

1. 点击卡片后详情始终是同一台机台

先检查按钮是否调用了this.onOpen(this.machine.id)。若误传固定字符串、第一项数组下标或展示编号,详情页拿到的就不是当前卡片的稳定 ID。然后检查MachineArchive是否把onOpenMachine原样传给卡片。

2. 点击后页面没有变化

检查Index.ets中的回调是否调用openDetail('machine', machineId),以及openDetail是否同时写入detailKind和detailId。只保存 ID 而不切换类型,页面仍会渲染原来的主内容;只切换类型而没有 ID,则详情页会进入缺失保护分支。

3. 返回后列表状态丢失或显示异常

检查返回动作是否统一走closeDetail()。当前实现会把详情类型恢复为none、清空详情 ID,并让主内容区域回到所选 Tab。不要让详情组件直接修改列表内部的筛选数组,否则返回路径会和列表状态耦合。

4. 详情页出现空标题或关联信息不对

检查machineById的入参是否仍是模型的id,并确认关联查询也使用currentMachine().id。如果在某处把code当作 ID,列表看似能正常显示,但 Repository 查找和关联数据都会失配。

十一、可复核的运行观察

可以按下面的顺序检查这条链路:

  1. 进入机台页面,确认列表中可见IM-120T-11卡片和“查看详情”按钮。
  2. 点击该按钮,确认页面标题变为IM-120T-11,并显示“精密外壳注塑机”。
  3. 核对基础信息中的锁模力、位置和运行状态是否与该卡片一致。
  4. 继续核对关联产品、最近调机记录与待处理异常是否出现,确认详情页使用的是同一台机台的 ID。
  5. 点击“返回”,确认回到机台列表,而不是跳转到其他详情类型。

这些步骤验证的是当前本地演示数据下的页面状态链路。它们不等同于真实设备控制、生产数据同步或服务端权限校验。

十二、小结

从机台卡片进入详情,关键不在于把一整个对象塞进点击事件,而在于让machine.id穿过清晰的边界:卡片上报 ID,列表转交回调,页面容器保存详情类型与 ID,详情页再由 Repository 查询完整对象。

这条链路让筛选、列表、详情和关联数据各自保持职责边界,也给找不到对象时的降级界面留出了位置。下一篇将继续停留在机台详情模块,拆解基础信息、维护状态与关联对象怎样组织成可读的详情页面。

附录:工程配置与版本说明

为了便于复现本文中的代码片段和运行现象,这里把当前文章系列对应的工程基线单独列出。本文所说的“当前工程”,指e_notebook项目的 HarmonyOS ArkTS 客户端,应用名称为“注塑工程师助手”,主要用于脱敏演示机台档案、产品档案、调机记录、参数模板、异常闭环、生产批次和看板报表等业务路径。

1. 应用与模块配置

  • 应用包名:com.atan.enotebook。
  • 应用版本:versionName为1.0.0,versionCode为1000000。
  • 工程模型:ArkTS / ArkUI Stage 模型。
  • 主模块:entry,模块类型为entry。
  • 入口 Ability:EntryAbility,入口文件为entry/src/main/ets/entryability/EntryAbility.ets。
  • 主页面配置:模块通过pages: "$profile:main_pages"读取页面列表。
  • 设备类型:当前模块声明支持phone、tablet和2in1。
  • 安装方式:deliveryWithInstall为true,installationFree为false,属于随应用安装的普通 entry 模块。

2. SDK 与 API 版本

  • DevEco Studio 版本:DevEco Studio Beta26.0.0.461。
  • 编译 SDK:HarmonyOS SDK API 26 Beta1,SDK 包版本为26.0.0.23。
  • SDK 平台信息:apiVersion为26,platformVersion为26.0.0,releaseType/stage为Beta1。
  • targetSdkVersion:26.0.0。
  • compatibleSdkVersion:6.1.1(24)。
  • API 口径说明:文章系列以 API 24 作为兼容目标进行表述;当前工程实际由 API 26 Beta SDK 编译,并在 API 24 模拟器上做过安装、启动和交互观察。因此,文中的“API 24 运行观察”表示兼容目标环境下的模拟器验证结果,不等同于使用 API 24 SDK 重新完成编译验证。

3. 构建与运行工具

  • 开发工具 IDE:DevEco Studio Beta,安装目录指向D:/Program Files/Huawei/DevEco Studio Beta。
  • SDK 路径:D:/Program Files/Huawei/DevEco Studio Beta/sdk。
  • 构建系统:Hvigor,工程入口hvigorfile.ts使用@ohos/hvigor-ohos-plugin的appTasks。
  • Hvigor 执行配置:开启 daemon、incremental、parallel 和 typeCheck,日志级别为info。
  • 构建脚本:本地build.ps1优先使用 DevEco Studio 自带的 JBR、Node.js、SDK 与 Hvigor,避免系统环境变量中的 Java 或 Node.js 版本干扰构建结果。
  • 调试产物:未配置签名时,本地构建生成entry/build/default/outputs/default/entry-default-unsigned.hap。这类 unsigned HAP 只用于本地调试和模拟器验证,正式发布前需要在 DevEco Studio 中补充签名配置。

4. 本系列文章的验证边界

  • 本系列代码以脱敏演示数据为主,Repository、Store、页面状态和组件边界都围绕本地演示闭环展开。
  • 已观察过的运行现象以文中对应截图、布局树和人工核对记录为准;没有重新核对的页面,不在单篇文章中扩大为完整结论。
  • 如果读者使用更新的 DevEco Studio、HarmonyOS SDK 或真机系统版本复现,API 差异、控件行为和签名流程可能会发生变化。遇到差异时,建议优先核对build-profile.json5、module.json5、SDK Manager 中安装的 API 版本,以及当前设备或模拟器的系统 API 等级。

附录 2:项目目录结构与设计意图

下面这份目录说明对应当前 DevEco Studio 中打开的harmonyos-app工程。截图里能看到的目录并不只是文件摆放习惯,它反映了一个 ArkTS Stage 工程的分层方式:应用级配置、业务模块、页面源码、资源文件、构建配置和过程归档分别放在不同位置,方便后续排查问题时先判断“问题属于配置、页面、数据、状态、资源,还是构建产物”。

harmonyos-app/ ├── AppScope/ # 应用级配置与全局资源入口 │ ├── app.json5 # bundleName、版本号、图标、应用标签等应用级元信息 │ └── resources/ # 应用级图标、字符串和基础资源 ├── entry/ # 主业务模块,当前 App 的主要页面和业务代码都在这里 │ ├── src/main/ets/ # ArkTS 源码根目录 │ │ ├── components/ # 可复用 ArkUI 组件,如底部导航、数据状态面板 │ │ ├── entryability/ # Stage 模型入口 Ability,负责应用启动入口 │ │ ├── features/ # 按业务域拆分的功能页面 │ │ │ ├── debug/ # 调机记录相关页面 │ │ │ ├── exceptions/ # 异常处置与闭环相关页面 │ │ │ ├── home/ # 首页看板与概览入口 │ │ │ ├── machines/ # 机台档案列表、详情和机台相关交互 │ │ │ ├── production/ # 生产批次、报工和结案门禁相关页面 │ │ │ ├── products/ # 产品档案、产品详情和关联信息 │ │ │ ├── reports/ # 周报、月报、班次报表和下钻入口 │ │ │ └── templates/ # 参数模板列表与详情 │ │ ├── models/ # 业务对象的数据结构,如 Machine、Product、DebugRecord │ │ ├── pages/ # 页面容器与导航装配,如 Index.ets │ │ ├── repositories/ # 脱敏演示数据、查询方法、快照持久化和数据重置边界 │ │ ├── stores/ # 页面路由、导航选择和共享状态规则 │ │ └── utils/ # 主题令牌、校验函数等通用工具 │ ├── src/main/resources/base/ # 模块级资源目录 │ │ ├── element/ # 字符串、颜色等基础资源声明 │ │ ├── media/ # 图标、启动图等媒体资源 │ │ └── profile/ # 页面 profile 配置,如 main_pages.json │ ├── src/main/module.json5 # entry 模块配置,声明 EntryAbility、设备类型和页面入口 │ ├── build-profile.json5 # 模块级构建目标、混淆和 target 配置 │ └── oh-package.json5 # entry 模块包信息与依赖声明 ├── hvigor/ # Hvigor 构建系统配置 │ └── hvigor-config.json5 # 构建执行参数,如增量、并行和类型检查 ├── build-profile.json5 # 工程级 SDK、targetSdkVersion、compatibleSdkVersion 配置 ├── hvigorfile.ts # 工程级构建任务入口,接入 appTasks ├── local.properties # 本机 SDK 路径配置 ├── oh-package.json5 # 工程级包信息与依赖声明 ├── build.ps1 # 本地构建脚本,固定使用 DevEco Studio 自带工具链 ├── document_claude/ # 开发过程归档、测试记录和验证材料 ├── .hvigor/ # Hvigor 生成的缓存和构建记录,不作为手写源码维护 ├── .idea/ # DevEco Studio / IntelliJ 工程配置,不承载业务逻辑 └── entry/build/ # 构建输出目录,HAP 和中间产物由构建流程生成

1. 为什么应用级配置放在AppScope

AppScope负责应用整体身份,而不是某个页面的业务逻辑。app.json5中的bundleName、versionName、versionCode、应用图标和应用标签,会影响安装包身份、桌面展示和版本识别。把这类配置放在应用级目录,可以避免业务页面为了改一个标题或图标而混入应用发布配置。

在当前工程中,AppScope更像“应用身份证”。它回答的是“这个 App 是谁、版本是多少、展示什么图标”,而不是“机台列表怎么筛选、详情页怎么返回”。

2. 为什么业务代码集中在entry/src/main/ets

entry是当前工程的主业务模块,src/main/ets是 ArkTS 源码根目录。截图里打开的MachineDetail.ets就位于features/machines下面,说明机台详情页被归入“机台业务域”,而不是随意放在全局页面目录中。

这种组织方式的好处是定位明确:机台问题优先看features/machines,产品问题优先看features/products,生产批次问题优先看features/production。当文章里讨论某个业务链路时,读者也能从目录直接反推代码位置。

3.components、features和pages的边界

components放的是可复用组件,例如底部导航、加载/空态/失败态面板。它们不应该直接知道“当前打开的是哪台机台”,而是通过参数和回调服务于不同页面。

features放的是业务域页面。每个子目录都围绕一个业务主题组织,例如machines负责机台档案,templates负责参数模板,exceptions负责异常闭环。业务页面可以组合组件,也可以读取模型和仓储,但应尽量把本业务域的显示和交互留在本目录内。

pages更偏页面容器和入口装配。当前Index.ets承担主页面状态切换、底部导航和详情路径分发等职责。它不应该塞满所有业务细节,而是负责把用户当前所在位置、打开对象和页面分支组织起来。

4.models、repositories和stores分别解决什么问题

models定义数据形状,例如机台、产品、调机记录、生产批次等对象有哪些字段。它让页面和仓储使用同一套类型语言,避免每个页面临时拼对象。

repositories定义数据来源和查询边界。当前工程使用脱敏演示数据和本地持久化快照,因此仓储层负责“从哪里取数据、按什么 ID 查询、怎样重置演示数据”。页面不直接关心数据是内置数组、Preferences 快照,还是后续真实接口。

stores定义页面级或应用级状态规则,例如当前导航项、路由分支、打开详情的类型和 ID。把状态规则从具体组件中抽出来,可以减少“列表、详情、导航互相覆盖状态”的问题。

5. 为什么资源放在resources/base

resources/base/element管字符串、颜色等声明,resources/base/media管图标和图片,resources/base/profile管页面 profile。它们和 ArkTS 页面代码分开,是为了让“界面逻辑”和“静态资源”各自清晰。

如果页面显示异常,先判断是布局代码问题还是资源引用问题。比如图标不显示,应优先检查media和资源引用;页面无法进入,应检查profile/main_pages.json和module.json5的页面声明;颜色或字符串不符合预期,则回到element下核对。

6. 构建目录和生成目录不要手工维护

.hvigor、entry/build和部分中间产物目录由构建系统生成,主要用于缓存、编译记录、HAP 输出和临时文件。它们可以帮助排查构建结果,但不应该作为手写业务代码维护。

当前调试 HAP 位于entry/build/default/outputs/default/entry-default-unsigned.hap。这个路径说明构建已经产出安装包,但它仍是 unsigned 调试产物;正式发布前应回到 DevEco Studio 的签名配置和发布流程,而不是直接修改build目录里的文件。

相关新闻

  • 网上无广告极简待办事项工具排行测评
  • 2026临沂GEO优化服务商 全维度测评指南 - 优企甄选
  • G-Helper完全指南:5分钟掌握华硕笔记本的轻量级控制艺术

最新新闻

  • 2026呼和浩特瓷砖空鼓翘边别硬拖!筑宅安微创修复消除安全隐患 - 筑宅安
  • 频谱分析仪本振失锁:环路滤波维修
  • 2026吕梁黄金回收白银回收铂金回收靠谱临街实体公安备案支持到店核验门店联系方式推荐
  • 锂电池保护板(BMS)工作原理、核心功能与选型设计全解析
  • C++头文件全包模式:编译模型、模板编程与工程实践权衡
  • HC社区管理系统:开源SaaS物业管理的完整解决方案

日新闻

  • ClickHouse版本管理深度实战:4步构建零风险升级与回滚体系
  • Java 23 种设计模式:从踩坑到精通 | 番外:责任链模式 —— 物流审批流程实战
  • 华硕笔记本性能解放指南:G-Helper轻量级控制工具全面解析

周新闻

  • 大连理工大学与东京大学联手打造的“主动型AI助手“
  • 170.2026年国家级科研瓶颈:超精密单点金刚石切削(SPDT)光学表面生成
  • SongBloom:革命性歌曲生成框架深度解析——如何通过交织自回归与扩散模型创作完整音乐

月新闻

  • ClickHouse版本管理深度实战:4步构建零风险升级与回滚体系
  • Java 23 种设计模式:从踩坑到精通 | 番外:责任链模式 —— 物流审批流程实战
  • 华硕笔记本性能解放指南:G-Helper轻量级控制工具全面解析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号