GridRow+ArkTS:折叠仓储复核表字段归属与断点回退【鸿蒙心迹】
仓库复核表不算复杂:输入批次号,填写外箱情况,再勾选三项核对结论。麻烦出在窗口从展开态回到窄屏的瞬间。编辑框可能被重新创建,勾选控件在另一列重现,操作者看到的是同一张表,代码却容易把它当成两组独立组件。只要把“字段数据属于谁”与“当前在哪一列显示”混在一起,布局切换就有机会让刚填的内容丢掉。这次把问题收敛成一个不依赖真实仓储接口的演示项目 FoldProof。任务号 FP-1810,批次 LOT-728,备注 “外箱完好”,三项检查依次是“包装、封签、批次号”,前两项选中,合计 2/3。示例展示窄屏 412vp、断点 xs、状态 DRAFT_SAFE。这些数据是构造的界面样例,不是设备实测记录。
## 一、断点改变的应当是位置,不是字段身份很多布局问题表面上是“折叠后显示错位”,实际是状态源出现了双份。比如开发时为了方便,把宽屏的备注输入框和窄屏的备注输入框分别写在两个 if 分支中,还分别持有默认值。用户刚输入“外箱完好”,窗口宽度跨过断点,另一个分支恢复到空字符串。这种现象不一定来自 ArkUI 丢状态,而是工程上把同一业务字段设计成了两个来源。比较稳妥的约定是:批次号、备注、三个复核结果构成一份业务草稿,布局只读取它。无论组件在左侧还是右侧、占四列还是六列、是否临时隐藏,业务字段都不创建第二份。断点回调产生的是表现层信息,而不是“创建一个新任务”的指令。对这类复核表,布局状态和业务状态必须分开命名,甚至最好由不同方法修改。我把界面需要的字段限定为 lotId、reviewNote、checks、currentBp、status。前三者代表用户输入,currentBp 代表当前样式,status 代表草稿检查结果。后两者可以因为设备变化更新,但不允许反向清空前三者。像 DRAFT_SAFE 这样的标签是应用自己定义的业务提示,不是 GridRow 返回的系统枚举值。## 二、先确定一份可复制、可比较的草稿下段 ArkTS 代码先解决勾选项修改时引用复用的问题。数组是可变对象,如果直接在多处共用同一引用,再让 UI 依靠另一个触发器刷新,就可能出现“数据显示已改、视觉状态没跟上”的争议。显式复制后重新赋值,便于让 @State 观察到数组更新,也让调试记录能够比较变化前后的值。tsinterface ReviewDraft { lotId: string; reviewNote: string; checks: boolean[];}function changeCheck(oldDraft: ReviewDraft, index: number, checked: boolean): ReviewDraft { if (index < 0 || index >= oldDraft.checks.length) { return oldDraft; } const nextChecks: boolean[] = oldDraft.checks.slice(); nextChecks[index] = checked; return { lotId: oldDraft.lotId, reviewNote: oldDraft.reviewNote, checks: nextChecks };}````ReviewDraft` 是应用自己的数据结构,并非鸿蒙框架接口;`changeCheck` 只是纯函数,负责生成更新后的快照。越界索引不改变状态,这一点看似琐碎,但在列表重排时非常重要:视图项的序号不是永远可靠的业务 ID,真实项目还应把检查项定义为稳定的 `checkId`,不应把数组位置当成可长期保存的标识。此例只有固定三项,才允许用位置表达。示例中即使“包装”和“封签”已完成,也不代表可以正式提交。第三项“批次号”仍未勾选,所以界面只显示 **2/3**,按钮定位为 **“保存草稿”**。这与“提交审批”“自动通过”是两个不同操作;将草稿安全态称为已审核通过,会误导业务和审计日志。## 三、让 GridRow 只处理列数,不接管内容ArkUI 的 `GridRow`、`GridCol` 支持按断点设定列数与跨度。这里把 `600vp` 当成**演示工程自定义阈值**,不是华为针对所有折叠屏要求的固定值:`xs` 使用四列,`sm` 使用十二列;字段在窄屏占满四列,在宽屏占六列。断点参照的是组件配置规则,应按具体容器或窗口的需求选择,不能把某一型号的物理分辨率直接代入 vp。下面的代码解决“布局改变后保留备注文本”的主体问题。为了突出字段拥有者,代码省略了装饰性组件和校验图标,页面文件为 `entry/src/main/ets/pages/FoldProofPage.ets`。ts@Entry@Componentstruct FoldProofPage { @State private reviewNote: string = ‘外箱完好’; @State private checks: boolean[] = [true, true, false]; @State private currentBp: string = ‘xs’; @State private status: string = ‘DRAFT_SAFE’; build() { Column({ space: 12 }) { Text(‘FoldProof · 仓储复核’) Text(‘FP-1810 · LOT-728’) GridRow({ columns: { xs: 4, sm: 12 }, breakpoints: { value: [‘600vp’] } }) { GridCol({ span: { xs: 4, sm: 6 } }) { TextInput({ text: this.reviewNote, placeholder: ‘复核备注’ }) .onChange((value: string) => { this.reviewNote = value; }) } GridCol({ span: { xs: 4, sm: 6 } }) { Text(已核对 ${this.checks.filter((x: boolean) => x).length}/3) } } .onBreakpointChange((bp: string) => { this.currentBp = bp; }) Text(断点 ${this.currentBp} · ${this.status}) Button(‘保存草稿’).onClick(() => { this.status = ‘DRAFT_SAFE’; }) }.width(‘100%’) }}注意 `reviewNote` 只有一份;回调中不出现 `reviewNote = ''` 或 `checks = []`。断点改变后只是更新 `currentBp`,新列数从布局规则推导。`GridRow` 允许定义断点变化回调,不代表任何大小变动都一定会触发相同次数的通知:真实页面应考虑首帧、分屏、旋转及系统字体缩放。代码中没有使用 `Preferences` 持久化,因此这里的“保存草稿”只代表**当前页面会话中的状态确认**;若需要应用重启后恢复,必须另接持久化层,不能把演示按钮描述为已写入磁盘。## 四、调试先确认值,再确认控件位置这张 DevEco 风格配图是生成的**演示界面**,并非本次进行过编译、运行或 HiLog 抓取的证明。真正诊断时,先记录状态快照,再观察列数,而不是从按钮看起来没有移动推断数据已经保存。建议在状态变更处打印任务 ID、批次、勾选数量、当前断点;日志里不应写姓名、联系方式或完整的敏感物料信息。对于应用内日志,生产构建还需要控制级别和脱敏。下面的代码解决“给状态转换留下可复算日志”的问题。它只组装演示字符串,避免绑定某个未经核实的系统日志封装,也便于测试框架对比精确结果。tsfunction summarizeDraft(bp: string, widthVp: number, draft: ReviewDraft): string[] { const count: number = draft.checks.filter((x: boolean) => x).length; return [ [FoldProof] FP-1810 bp=${bp} width=${widthVp}vp, [FoldProof] FP-1810 lot=${draft.lotId} checks=${count}/3, ‘[FoldProof] FP-1810 state=DRAFT_SAFE’ ];}```代入本篇构造数据,三行应当依次是 [FoldProof] FP-1810 bp=xs width=412vp、[FoldProof] FP-1810 lot=LOT-728 checks=2/3、[FoldProof] FP-1810 state=DRAFT_SAFE。日志字符串是期望样例,不是声称已经在某个开发板上测到的结果。若切换回宽屏,新的断点和宽度应改变;批次、备注以及 2/3 检查数量不应随着布局被重置。这个不变量比“截图长得一致”更值得写成自动化断言。为了模拟回退,可先把宽屏容器调至示例的 784vp,确认对应规则的 sm 分支,再改为 412vp 并检查 xs。宽度应来自当前容器或设备工具的可验证读数,这里给出的两组数字只是本地测试方案的输入。只有确认输入控件内容、勾选结果、光标行为、提交门禁都正确,才能把“回退测试通过”写进实际项目报告。## 五、结果页展示什么,审阅时就能判断什么单张手机演示图只保留一张复核表:顶部有任务 FP-1810 与批次 LOT-728,备注框是 “外箱完好”;“包装、封签、批次号”三项中前两项被勾选,显示 2/3;底部列出 412vp、xs 和 DRAFT_SAFE,并提供 “保存草稿” 按钮。它不含“审核已通过”这样的虚假终态,也不试图以静态图证明恢复耗时。
最容易忽略的并非断点阈值,而是保存动作与业务动作的界线。设备刚变窄,用户立刻点保存,若数据快照来自某个旧组件分支,保存的可能是上一轮的空值。因此,正式工程应把保存函数的输入限定为同一份 ReviewDraft,必要时在提交前检查任务号仍是 FP-1810、当前页面没有切到其他批次。窗口大小不应该成为更新业务主键的理由。还有两个边界需要写清。其一,复杂表单中子组件可能在折叠切换时销毁与创建,焦点及输入法状态不保证随业务字段自动保持;焦点恢复应另做明确策略。其二,onBreakpointChange 只告诉布局落入哪个区间,它本身不负责保护异步保存、图片附件、权限状态和后端并发版本。若复核流程接入服务端,需要另外增加乐观锁或版本比较,不能把 @State 当作并发控制。## 六、收口:用不变量检验布局质量这类问题最后可以收成三条可验证的不变量:同一业务字段在任何屏幕形态下只有一个状态源;断点回调不改变任务及输入快照;草稿状态只说明本地数据仍被当前页面持有,不替代正式提交流程。基于这些约束,宽屏、窄屏和折叠态才可以共用一套复核规则。图片只是把这些关系表现出来,不能替代 DevEco 编译和多设备运行。资料依据: 华为 GridRow 官方参考;华为响应式栅格布局指导。本文未将演示阈值、任务 ID 或状态名描述为系统官方常量,ArkTS 示例仍需在目标工程的实际 SDK 与 DevEco 环境中编译验证。
更多推荐




所有评论(0)