鸿蒙原生开发手记:徒步迹 - @Watch 与 @ObjectLink 深入理解

发布时间:2026/7/14 2:06:43

鸿蒙原生开发手记:徒步迹 - @Watch 与 @ObjectLink 深入理解
掌握状态监听和对象级响应提升 ArkUI 状态管理能力一、前言ArkUI 的状态管理体系中除了基础的 State/Prop/Link 和跨级通信的 Provide/Consume还有两个重要的装饰器Watch 和 ObjectLink。Watch监听状态变化执行回调函数ObjectLink监听对象的属性级变化避免不必要的重新渲染二、Watch - 状态监听2.1 基本用法Watch 用于监听 State 变量的变化变化时自动执行回调Componentstruct DistanceTracker{StateWatch(onDistanceChanged)distance:number0;StateWatch(onStatusChanged)status:stringidle;// Watch 回调每次 distance 变化时触发onDistanceChanged():void{console.log(距离更新:${this.distance}km);this.checkMilestone();}onStatusChanged():void{console.log(状态变更:${this.status});}checkMilestone():void{if(this.distance10this.distance10.01){console.log( 达到10公里里程碑);}}build(){Column(){Text(距离:${this.distance.toFixed(2)}km);Button(模拟前进).onClick((){this.distance0.5;// 触发 Watch 回调});Button(停止).onClick((){this.statuscompleted;// 触发 Watch 回调});}}}2.2 与 Link/Prop 配合Componentstruct ChildComponent{LinkWatch(onValueChange)sharedValue:number;onValueChange():void{console.log(子组件检测到值变化:${this.sharedValue});// 可以在此执行数据验证、副作用等}}2.3 Watch 与计算属性由于 ArkTS 不支持计算属性getter可以用 Watch 模拟Componentstruct RouteStats{StateWatch(calcDerivedData)distance:number0;StateWatch(calcDerivedData)duration:number0;Statepace:string0\00;// 派生状态StateavgSpeed:number0;// 派生状态calcDerivedData():void{// 当 distance 或 duration 变化时重新计算派生数据if(this.duration0this.distance0){this.pacethis.formatPace(this.duration,this.distance);this.avgSpeedthis.distance/(this.duration/3600);}}formatPace(seconds:number,km:number):string{constpacePerKmseconds/km;constminMath.floor(pacePerKm/60);constsecMath.floor(pacePerKm%60);return${min}${sec.toString().padStart(2,0)};}build(){Column(){Text(配速:${this.pace});Text(均速:${this.avgSpeed.toFixed(1)}km/h);}}}三、ObjectLink - 对象属性级监听3.1 解决的问题默认情况下State 监听的是对象引用变化而不是属性变化// ❌ 以下方式不会触发 UI 更新Stateroute{name:香山,distance:5};this.route.distance10;// 属性修改UI 不更新// ✅ 需要重新赋值this.route{...this.route,distance:10};ObjectLink 解决了这个问题可以监听对象属性的变化。3.2 使用 ObjectLink// 定义类需要使用 Observed 装饰ObservedclassTrackRecord{name:string;distance:number0;duration:number0;points:Coordinate[][];constructor(name:string){this.namename;}}// 父组件Componentstruct TrackDetail{Staterecord:TrackRecordnewTrackRecord(晨间徒步);build(){Column(){// 传入 ObjectLinkTrackInfo({record:this.record});Button(更新距离).onClick((){// ObjectLink 可以监听到属性变化this.record.distance1;});}}}// 子组件 - 使用 ObjectLink 接收Componentstruct TrackInfo{ObjectLinkrecord:TrackRecord;build(){Column(){Text(名称:${this.record.name});Text(距离:${this.record.distance.toFixed(1)}km);Text(用时:${this.record.duration}s);}}}3.3 Observed 装饰器使用 ObjectLink 前类必须用Observed装饰ObservedclassCoordinate{latitude:number0;longitude:number0;altitude:number0;}ObservedclassTrackPoint{coord:CoordinatenewCoordinate();heartRate:number0;timestamp:number0;}四、实战徒步迹实时轨迹追踪结合 ObjectLink 和 Watch实现轨迹追踪的实时更新ObservedclassTrackSession{name:string;startTime:number0;distance:number0;duration:number0;calories:number0;points:Coordinate[][];}Componentstruct TrackingController{ObjectLinksession:TrackSession;StatetimerId:number-1;start():void{this.session.startTimeDate.now();this.timerIdsetInterval((){this.session.duration;this.session.distance0.005;// 模拟轨迹点letpointnewCoordinate();point.latitude39.908Math.random()*0.01;point.longitude116.397Math.random()*0.01;this.session.points.push(point);},1000);}stop():void{clearInterval(this.timerId);}build(){Column(){Button(开始追踪).onClick(()this.start());Button(停止).onClick(()this.stop());}}}Componentstruct TrackingDisplay{ObjectLinksession:TrackSession;build(){Column(){Text(距离:${session.distance.toFixed(2)}km);Text(时长:${session.duration}s);Text(点数:${session.points.length});}}}EntryComponentstruct TrackingPage{StatetrackSession:TrackSessionnewTrackSession();build(){Column(){Text(轨迹记录).fontSize(20).fontWeight(FontWeight.Bold);TrackingDisplay({session:this.trackSession});TrackingController({session:this.trackSession});}.width(100%).height(100%).padding(16);}}五、Watch 与 ObjectLink 对比特性WatchObjectLink用途监听变化执行副作用监听属性级变化更新 UI使用位置状态变量上子组件参数接收依赖搭配 State/Link/Prop搭配 Observed 类触发时机变量赋值时对象属性变化时典型场景数据持久化、日志记录表单、实时数据展示六、性能优化建议避免频繁 Watch 回调中的复杂计算ObjectLink 适用于大型对象小型对象用 Prop 即可合理使用 Observed 范围不要过度装饰// ✅ 好在 Watch 中做轻量操作Watch(saveState)onStateChange():void{AppStorage.set(lastDistance,this.distance);}// ❌ 不好在 Watch 中做耗时操作onStateChange():void{this.heavyComputation();// 避免this.syncToServer();// 避免}七、总结Watch 和 ObjectLink 是 ArkUI 状态管理的高级特性。Watch 让你在状态变化时执行自定义逻辑ObjectLink 让你以更自然的方式修改对象属性。合理运用这些工具可以构建出响应迅速、代码优雅的鸿蒙应用。第一阶段1-10篇到此结束下一阶段我们将进入徒步迹核心页面的实战开发。下一篇预告鸿蒙原生开发手记徒步迹 - 应用生命周期与AbilityStage

相关新闻

数字图像处理实战:从零构建车牌识别系统

数字图像处理实战:从零构建车牌识别系统

2026/7/14 2:06:43

1. 车牌识别系统概述车牌识别系统是计算机视觉领域的一个经典应用场景,它能够自动从车辆图像中提取车牌信息。想象一下,当你开车进入停车场时,闸机自动抬起栏杆的场景——这就是车牌识别技术在日常生活中的典型应用。这套系统看似简单&#x…

自监督去噪:Noiser2Noise实战与噪声建模探讨

自监督去噪:Noiser2Noise实战与噪声建模探讨

2026/7/14 1:56:42

1. 自监督去噪的核心概念 想象一下你在一个嘈杂的咖啡馆里录音,背景里充斥着杯盘碰撞声和人群交谈声。传统方法需要你同时录制一段纯净的人声作为参考才能消除噪音,这显然不现实。Noiser2Noise就像一位聪明的音频工程师,它不需要原始纯净录音…

微信小程序‘机器人兔兔’源码包:含完整项目结构、6张核心界面截图与本地可运行代码

微信小程序‘机器人兔兔’源码包:含完整项目结构、6张核心界面截图与本地可运行代码

2026/7/14 1:56:42

本文还有配套的精品资源,点击获取 简介:这个资源是微信小程序‘机器人兔兔’的完整开发交付物,包含基于原生框架开发的全部源码文件,目录结构清晰,涵盖WXML、WXSS、JS三端代码,已移除敏感配置信息&#…

YOLOv8蜜蜂识别检测系统:从环境配置到实战部署完整指南

YOLOv8蜜蜂识别检测系统:从环境配置到实战部署完整指南

2026/7/14 6:06:55

这次我们来看一个基于YOLOv8的蜜蜂识别检测系统,这是一个完整的目标检测项目,包含源码、数据集、模型权重和UI界面。对于想要学习YOLOv8实战应用或者需要开发农业监测、生物识别系统的开发者来说,这个项目提供了很好的起点。YOLOv8作为YOLO系…

2025年C++性能分析工具全景指南:从Perf到eBPF的实战工作流

2025年C++性能分析工具全景指南:从Perf到eBPF的实战工作流

2026/7/14 6:06:55

1. 项目概述:为什么C开发者必须关注性能分析工具?如果你是一名C开发者,无论你是深耕于游戏引擎、高频交易系统、嵌入式设备还是大规模后端服务,性能这个词一定是你日常工作中绕不开的“紧箍咒”。C以其对硬件资源的直接掌控能力和…

零信任彻底普及!2026企业网安标配:永不信任、永远验证

零信任彻底普及!2026企业网安标配:永不信任、永远验证

2026/7/14 6:06:55

📌 三句大白话,搞懂零信任爆火原因第一:传统边界安全彻底失效,零信任成唯一解。以前企业靠防火墙、内网外网隔离防护,现在远程办公、云办公、移动设备接入常态化,固定网络边界彻底瓦解,传统“内…

Mellanox IB卡驱动安装与模式切换实战解析

Mellanox IB卡驱动安装与模式切换实战解析

2026/7/14 6:06:55

1. Mellanox IB卡驱动安装全攻略 刚拿到Mellanox IB卡时,我最头疼的就是驱动安装。经过多次实战,我总结出一套适合新手的安装流程。以CentOS 8.2系统为例,当你把CX354A卡插入PCIe插槽后,系统其实已经自带了mlx4_core内核驱动。用…

无密码认证全面来袭!2026告别密码泄露,FIDO2成安全新标配

无密码认证全面来袭!2026告别密码泄露,FIDO2成安全新标配

2026/7/14 6:06:55

📌 三句大白话,读懂无密码安全革命第一:密码本身,就是最大的安全漏洞。弱密码、重复密码、密码泄露、暴力破解、钓鱼套取,90%的账号安全事故,根源都在“密码认证体系”本身,传统密码早已无法适配…

Wand-Enhancer:如何免费解锁WeMod专业版功能并实现远程控制?

Wand-Enhancer:如何免费解锁WeMod专业版功能并实现远程控制?

2026/7/14 5:56:55

Wand-Enhancer:如何免费解锁WeMod专业版功能并实现远程控制? 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/GitHub_Trending/we/Wand-Enhancer 还在为WeMod&a…

Unity游戏文本翻译架构深度解析:XUnity.AutoTranslator的技术实现与工程实践

Unity游戏文本翻译架构深度解析:XUnity.AutoTranslator的技术实现与工程实践

2026/7/13 7:41:16

Unity游戏文本翻译架构深度解析:XUnity.AutoTranslator的技术实现与工程实践 【免费下载链接】XUnity.AutoTranslator 项目地址: https://gitcode.com/gh_mirrors/xu/XUnity.AutoTranslator XUnity.AutoTranslator作为Unity游戏社区中最成熟的文本翻译解决方…

openEuler Raspberry Pi Kernel设备驱动开发指南:为树莓派硬件添加支持

openEuler Raspberry Pi Kernel设备驱动开发指南:为树莓派硬件添加支持

2026/7/13 20:43:19

openEuler Raspberry Pi Kernel设备驱动开发指南:为树莓派硬件添加支持 【免费下载链接】raspberrypi-kernel It provides openEuler kernel source for Raspberry Pi 项目地址: https://gitcode.com/openeuler/raspberrypi-kernel 前往项目官网免费下载&…

openEuler系统集成测试实战:基于smoke-test套件的环境验证技巧

openEuler系统集成测试实战:基于smoke-test套件的环境验证技巧

2026/7/13 20:43:10

openEuler系统集成测试实战:基于smoke-test套件的环境验证技巧 【免费下载链接】integration-test The repo contains test suits for system integration test 项目地址: https://gitcode.com/openeuler/integration-test 前往项目官网免费下载:…

XUnity.AutoTranslator 游戏实时翻译插件:从原理到实战的完整指南

XUnity.AutoTranslator 游戏实时翻译插件:从原理到实战的完整指南

2026/7/14 0:06:37

1. 项目概述:当游戏语言成为一堵墙作为一名玩了十几年日系、欧美独立游戏的“老油条”,我太懂那种面对一款心仪已久、画风玩法都戳中G点的游戏,却因为语言不通而望而却步的痛了。尤其是那些基于Unity引擎开发的、体量不大但内容精良的作品&am…

2026普通文员学数据分析的价值

2026普通文员学数据分析的价值

2026/7/14 0:06:37

一、2026年普通文员学习数据分析的必要性随着数字化转型加速,数据分析技能正逐渐成为职场基础能力。普通文员学习数据分析可以提升工作效率、增强竞争力,并为职业转型提供更多可能性。二、数据分析对文员的价值自动化办公:通过数据分析工具&a…

2026从计划员到主管,生产管理者学数据分析有用吗?

2026从计划员到主管,生产管理者学数据分析有用吗?

2026/7/14 0:06:37

一、生产管理领域的职业发展路径 从计划员到主管的角色转变,是生产管理者职业发展的典型路径。计划员主要负责生产排程、库存管理和资源协调等基础工作,而主管则需要承担团队管理、决策支持和效率优化等更高级别的职责。这种转变不仅仅是职位的提升&…