ArkTS V2 状态管理三坑:@Local 判据 / 引用替换 / 双通道更新(HarmonyOS)
现象: 消散卡重构后选图:白点粒子层正常显示,底图却永不渲染、"等待选图"占位文字不消失;另一处 mask 进度推进到 100 底图却毫无擦除;多层粒子调参时,热参数要平滑生效、结构参数要可靠整层重建,两套需求混在一起顾此失彼。
原因: build 里读到的成员(if 条件/布局计算入参)从 @Local 降级成了普通 private,V2 最小更新只追踪 @Local 及以上,plain private 赋值后不触发重求值;
ProgressMask.updateProgress()在 @ComponentV2 + private 实例上下文不生效;热参数热更新与结构参数重建是两条不同通道。解决: 判据一句话------"build 会不会读它",读就 @Local;mask 改 @Local 持有 + 每 tick
new ProgressMask(...)引用替换;结构参数走structVer+++ ForEach key 变化整层重建。
坑14:plain private 不重求值
重构卡 3 时 pickedUri / imgAspect 从 @Local 降级成普通 private。build 里的 if (pickedUri.length) 和 clip 高度计算(imgAspect)读的是 plain private,赋值后不触发重求值------底图分支是死状态。
诡异的是粒子层照常更新------sparkleRows / modeVer 是 @Local。代偿存在,但不可依赖:其他卡同模式没炸,只是 if 条件里恰好有 @Local 成员代偿触发。
判据:build 会不会读它。 build 里读到的每个成员------if 条件、属性绑定、布局计算入参------必须 @Local。补装饰器即愈。
坑13:Stack 默认居中重定位 + ProgressMask 失效
做图片擦除效果时的两个混淆点:
- 预览 Stack 重定位 :默认
alignContent = Center把动态高度的裁切 Column 反复重新居中,表现为裁切窗口"顶边下移/残余图重新居中"。解法:外包全尺寸Stack().alignContent(Alignment.TopStart)锚死顶部 - ProgressMask 不生效 :
updateProgress()在 @ComponentV2 + private 实例上下文不生效(真机裸观察"mask 实际不擦除"修正了代码层"进度正常推进"的误判)。解法:实例重建法 ------@Local 持有 + 每 ticknew ProgressMask(...),用引用替换驱动重新应用
双通道更新设计
Particle 参数既要热更新又要结构性变更时,分两条通道各走各的:
| 通道 | 适用 | 机制 |
|---|---|---|
| live 热更新 | emitRate / 位置 / 尺寸等热参数 | .emitter() 链式热更新,平滑生效 |
| struct 重建 | 层增删/重排等结构参数 | structVer++ + layers.slice() → ForEach key 变化 → 整层重建 |
三个配套细节:
- 结构滑条 endOnlyVal :只在
SliderChangeMode.End(松手)才回调写入,避免拖动中整层重建 - id 全局单调递增 :
decodeLayers(raw, idBase)由调用方传基址,防 ForEach 同 key 不重建 - 引用替换优先:驱动属性重新应用,"new 实例引用替换"比可变实例方法可靠(坑 13 的教训)
标签
#HarmonyOS #ArkTS #ComponentV2 #Local #状态管理 #ArkUI
📹 效果演示 :本文的「照片消散」动态效果实录会发在抖音------号 581821159(天行健之初九),截图看不出的粒子细节,视频一眼就懂。
懿路向前 · AI辅助整理 · 2026-10-12