HarmonyOS7 对象监听任务页实战:@Observed 与 @ObjectLink 不只是会用,还要用得顺手
文章目录先看两个被观察的对象addScore() 比构造函数更值得看ObjectLink 适合拆子组件页面结构怎么看完整代码写在最后Observed和ObjectLink很适合讲“对象级响应式”但只讲概念会有点飘。这个案例把它放到用户资料和每日任务里就好理解多了用户积分变了资料卡要刷新任务完成了任务行也要刷新。这类页面如果只靠普通对象很容易出现“数据确实改了但 UI 没动”的情况。HarmonyOS7 里做对象监听关键就是把对象本身纳入响应式体系。先看两个被观察的对象代码里有两个Observed类UserProfile和Task。前者保存用户名、年龄、等级、头像和积分后者保存任务 id、标题、完成状态和奖励积分。它们不是随便写的普通类。加上Observed后子组件可以通过ObjectLink观察对象属性变化。这样父组件传给子组件的不是一份死数据而是可以继续响应更新的对象。addScore()比构造函数更值得看用户完成任务后积分会增加积分达到等级阈值时还会升级。这个逻辑放在UserProfile.addScore()里比散落在按钮点击事件中清楚很多。addScore(pts:number){this.scoreptsif(this.scorethis.level*100){this.levelthis.scorethis.score-(this.level-1)*100}}这段代码说明了一个很实用的写法对象自己的业务规则尽量放回对象内部。页面只负责触发动作不要把升级规则、积分计算、UI 刷新混在一个点击事件里。ObjectLink适合拆子组件像用户卡片、任务行这种组件如果每个字段都用Prop传参数会越来越多而且子组件无法自然感知对象内部变化。ObjectLink更适合这种“整对象传入局部字段更新”的场景。不过它也不是万能的。只有对象被Observed标记ObjectLink才有意义如果对象结构经常临时加字段ArkTS 的静态类型也不会喜欢这种写法。页面结构怎么看ObservedProfilePage里维护了userProfile和taskList。用户资料卡关注积分和等级每日任务列表关注完成状态。读代码时可以先看两个类再看子组件如何接收对象最后看完成任务时怎么更新积分。如果你做的是用户中心、任务系统、订单卡片这类页面这种写法比一堆零散State更容易维护。完整代码下面是完整代码。入口组件名是ObservedProfilePage适合拿来练习 HarmonyOS7 中对象状态监听和子组件刷新。// Observed 与 ObjectLink 对象监听ObservedclassUserProfile{name:stringage:numberlevel:numberavatar:stringscore:numberconstructor(name:string,age:number,level:number,avatar:string,score:number){this.namenamethis.ageagethis.levellevelthis.avataravatarthis.scorescore}addScore(pts:number){this.scoreptsif(this.scorethis.level*100){this.levelthis.scorethis.score-(this.level-1)*100}}}ObservedclassTask{id:numbertitle:stringdone:booleanpoints:numberconstructor(id:number,title:string,done:boolean,points:number){this.ididthis.titletitlethis.donedonethis.pointspoints}}// 子组件用户卡片ObjectLink 监听 UserProfileComponentstruct UserCard{ObjectLinkuser:UserProfilebuild(){Column({space:10}){Row({space:12}){Text(this.user.avatar).fontSize(36).width(60).height(60).textAlign(TextAlign.Center).backgroundColor(#EFF6FF).borderRadius(30)Column({space:4}){Text(this.user.name).fontSize(18).fontWeight(FontWeight.Bold).fontColor(#111827)Row({space:8}){Text(Lv.${this.user.level}).fontSize(12).fontColor(Color.White).backgroundColor(#2563EB).padding({left:8,right:8,top:2,bottom:2}).borderRadius(10)Text(年龄${this.user.age}).fontSize(12).fontColor(#6B7280)}}.alignItems(HorizontalAlign.Start).layoutWeight(1)Column({space:2}){Text(this.user.score.toString()).fontSize(20).fontWeight(FontWeight.Bold).fontColor(#D97706)Text(积分).fontSize(11).fontColor(#9CA3AF)}.alignItems(HorizontalAlign.Center)}.width(100%).alignItems(VerticalAlign.Center)// 经验进度条Column({space:4}){Row(){Text(经验值).fontSize(12).fontColor(#6B7280).layoutWeight(1)Text(${this.user.score}/${this.user.level*100}).fontSize(12).fontColor(#2563EB)}Progress({value:this.user.score,total:this.user.level*100,type:ProgressType.Linear}).color(#2563EB).backgroundColor(#E5E7EB).style({strokeWidth:8}).width(100%)}}.width(100%).padding(16).backgroundColor(Color.White).borderRadius(12).shadow({radius:8,color:rgba(0,0,0,0.06),offsetY:2})}}// 子组件任务行ObjectLink 监听 TaskComponentstruct TaskRow{ObjectLinktask:TaskonComplete:(pts:number)void(){}build(){Row({space:12}){Text(this.task.done?✅:⬜).fontSize(22).onClick((){if(!this.task.done){this.task.donetruethis.onComplete(this.task.points)}})Column({space:3}){Text(this.task.title).fontSize(14).fontColor(this.task.done?#9CA3AF:#111827).decoration({type:this.task.done?TextDecorationType.LineThrough:TextDecorationType.None})Text(${this.task.points}积分).fontSize(12).fontColor(this.task.done?#9CA3AF:#D97706)}.alignItems(HorizontalAlign.Start).layoutWeight(1)if(!this.task.done){Text(去完成).fontSize(12).fontColor(#2563EB).backgroundColor(#EFF6FF).padding({left:10,right:10,top:4,bottom:4}).borderRadius(12).onClick((){this.task.donetruethis.onComplete(this.task.points)})}else{Text(已完成).fontSize(12).fontColor(#059669).backgroundColor(#D1FAE5).padding({left:10,right:10,top:4,bottom:4}).borderRadius(12)}}.width(100%).padding({left:16,right:16,top:12,bottom:12}).backgroundColor(this.task.done?#FAFAFA:Color.White).borderRadius(10).alignItems(VerticalAlign.Center)}}EntryComponentstruct ObservedProfilePage{StateuserProfile:UserProfilenewUserProfile(张三,25,3,‍,65)StatetaskList:Task[][newTask(1,完成每日签到,false,10),newTask(2,阅读一篇技术文章,false,20),newTask(3,完成一个练习项目,false,50),newTask(4,参与社区问答,false,30),newTask(5,分享学习心得,false,40),]build(){Column({space:0}){// 标题Text(Observed ObjectLink).fontSize(18).fontWeight(FontWeight.Bold).fontColor(#111827).width(100%).padding({left:20,right:20,top:20,bottom:4})Text(监听对象内部属性变化实现嵌套数据驱动视图).fontSize(13).fontColor(#6B7280).width(100%).padding({left:20,right:20,bottom:12})// 说明Row(){Text().fontSize(14).margin({right:6})Text(Observed 类 ObjectLink 子组件对象属性变化时触发子组件重渲染).fontSize(12).fontColor(#1E40AF).layoutWeight(1)}.width(100%).padding({left:16,right:16,top:8,bottom:8}).backgroundColor(#DBEAFE).margin({bottom:12}).alignItems(VerticalAlign.Top)Scroll(){Column({space:12}){// 用户卡片UserCard({user:this.userProfile}).margin({left:20,right:20})// 操作按钮Row({space:10}){Button(10 积分).fontSize(12).fontColor(#D97706).backgroundColor(#FEF3C7).borderRadius(16).padding({left:14,right:14,top:8,bottom:8}).onClick((){this.userProfile.addScore(10)})Button(50 积分).fontSize(12).fontColor(#059669).backgroundColor(#D1FAE5).borderRadius(16).padding({left:14,right:14,top:8,bottom:8}).onClick((){this.userProfile.addScore(50)})Button(年龄1).fontSize(12).fontColor(#7C3AED).backgroundColor(#F5F3FF).borderRadius(16).padding({left:14,right:14,top:8,bottom:8}).onClick((){this.userProfile.age})}.padding({left:20,right:20})// 任务列表标题Text(每日任务完成任务获得积分).fontSize(14).fontWeight(FontWeight.Bold).fontColor(#374151).padding({left:20})Column({space:8}){ForEach(this.taskList,(task:Task){TaskRow({task:task,onComplete:(pts:number){this.userProfile.addScore(pts)}}).margin({left:20,right:20})},(task:Task)task.id.toString())}// 已完成统计Row({space:12}){Text(✅).fontSize(20)Text(已完成${this.taskList.filter((t:Task)t.done).length}/${this.taskList.length}任务).fontSize(14).fontColor(#374151).layoutWeight(1)Text(${this.taskList.filter((t:Task)t.done).reduce((s:number,t:Task)st.points,0)}积分).fontSize(14).fontWeight(FontWeight.Bold).fontColor(#D97706)}.width(100%).padding({left:20,right:20,top:12,bottom:12}).backgroundColor(#FFFBEB).margin({bottom:24}).alignItems(VerticalAlign.Center)}}.layoutWeight(1)}.width(100%).height(100%).backgroundColor(#F9FAFB)}}写在最后这个例子不复杂但很适合反复看。很多 ArkUI 页面写不顺其实不是组件不会用而是状态、结构和反馈没有放在一起设计。

相关新闻

单片机实验2

单片机实验2

一、IIC总线协议1.简介定义:是一种广泛用于嵌入式系统的同步、串行、半双工通信协议,用于在同一块电路板上的集成电路之间进行通信。I2C总线:是一种物理通信架构,用于连接多个设备,实现设备之间的数据传输。I2C协议&am…

2026/7/20 5:36:09 阅读更多 →
C++23 <stacktrace>库实战:跨平台调试与异常处理新利器

C++23 <stacktrace>库实战:跨平台调试与异常处理新利器

1. 项目概述:为什么我们需要一个标准化的栈踪迹库?调试,大概是每个C开发者又爱又恨的环节。爱的是,当程序在你面前崩溃,而你通过蛛丝马迹最终定位到那个深藏不露的bug时,那种成就感无与伦比;恨的…

2026/7/20 7:01:27 阅读更多 →
Spring框架@RequestAttribute注解详解与应用实践

Spring框架@RequestAttribute注解详解与应用实践

1. RequestAttribute 注解深度解析在Spring框架中,RequestAttribute注解是一个相对小众但非常实用的注解。它主要用于从请求作用域(request scope)中获取预先存在的属性值。与大家更熟悉的RequestParam不同,RequestAttribute不是用来获取请求参数的&…

2026/7/20 7:04:46 阅读更多 →

最新新闻

开源算法热潮下,技术人如何抓住 AI 业务落地新机遇

开源算法热潮下,技术人如何抓住 AI 业务落地新机遇

最近两年,整个技术行业的氛围发生了翻天覆地的变化。放在三四年前,AI大模型还只是实验室、大厂研究院的前沿技术,普通开发、运维、网工、安全测试从业者,日常工作和AI几乎毫无关联。大家每天的工作依旧是写重复代码、人工巡检网络…

2026/7/20 19:23:24 阅读更多 →
Fable 5模型回归事件:安全与性能的权衡分析

Fable 5模型回归事件:安全与性能的权衡分析

1. Fable 5回归事件全貌解析2026年7月1日,Anthropic公司宣布重新部署Claude Fable 5模型,距离该模型因出口管制被紧急下架仅过去18天。这次回归本应是技术圈的盛事,却在24小时内遭遇用户集体差评风暴。官方公告中提到的"更新网络安全防护…

2026/7/20 19:23:24 阅读更多 →
Flutter 鸿蒙Text组件详解

Flutter 鸿蒙Text组件详解

作者:孟少康(世人万千) 仓库地址:https://gitcode.com/feng8403000/FlutterfromBeginnertoAdvancedForHarmonyOS.git 联系邮箱:372699828qq.com 概述 Text组件是Flutter中最基础也是最常用的UI组件之一,用…

2026/7/20 19:23:24 阅读更多 →
【SI_高速串行信号03】快速掌握高速串行信号示波器均衡技术操作指南

【SI_高速串行信号03】快速掌握高速串行信号示波器均衡技术操作指南

目录 1. 高速串行信号均衡概述 1.1. 均衡技术的核心目标 1.2. 主流均衡技术分类与原理 2. 示波器均衡操作指南 2.1. 示波器均衡软件使用准备 2.2. 示波器均衡技术操作步骤 3. 示波器均衡软件使用注意事项 3.1. 均衡的 “双刃剑” 特性 3.2. 恶劣信号的时钟恢复前置策略…

2026/7/20 19:23:24 阅读更多 →
KL-Loss社区贡献指南:如何参与项目开发、提交PR和报告Issue

KL-Loss社区贡献指南:如何参与项目开发、提交PR和报告Issue

KL-Loss社区贡献指南:如何参与项目开发、提交PR和报告Issue 【免费下载链接】KL-Loss Bounding Box Regression with Uncertainty for Accurate Object Detection (CVPR19) 项目地址: https://gitcode.com/gh_mirrors/kl/KL-Loss KL-Loss是一个专注于目标检测…

2026/7/20 19:23:24 阅读更多 →
Replication Manager插件系统:如何开发自定义日志插件

Replication Manager插件系统:如何开发自定义日志插件

Replication Manager插件系统:如何开发自定义日志插件 【免费下载链接】replication-manager Signal 18 repman - Replication Manager for MySQL / MariaDB / Percona Server 项目地址: https://gitcode.com/gh_mirrors/re/replication-manager Replication…

2026/7/20 19:22:24 阅读更多 →

日新闻

2026 WAIC:努比亚二代“豆包手机”NaviX Ultra亮相,智能体验全面升级!

2026 WAIC:努比亚二代“豆包手机”NaviX Ultra亮相,智能体验全面升级!

7月18日智东西消息,在2026 WAIC期间,努比亚联合字节豆包打造的二代“豆包手机”努比亚NaviX Ultra首次亮相,相比一代有诸多升级。智能体手机理念中兴通讯终端事业部总裁、努比亚总裁倪飞表示,智能体手机要从人操作手机变为手机帮人…

2026/7/20 0:00:34 阅读更多 →
努比亚NaviX Ultra亮相WAIC,智能体手机能否让用户生活更简单?

努比亚NaviX Ultra亮相WAIC,智能体手机能否让用户生活更简单?

努比亚NaviX Ultra:外观与功能双升级在2026 WAIC期间,首次亮相的努比亚NaviX Ultra吸引了众多目光。它是努比亚联合字节豆包打造的二代“豆包手机”,与一代努比亚M153相比,外观设计变化较大。其机身背部搭载横向排布的大尺寸影像模…

2026/7/20 0:00:34 阅读更多 →
C# 将逗号分割的字符串转换为long,并添加到List<long>

C# 将逗号分割的字符串转换为long,并添加到List<long>

目录 方法1:使用Split和Convert.ToInt64 方法2:使用LINQ的Select和ToList 方法3:使用TryParse进行异常安全转换(推荐) 如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天…

2026/7/20 0:00:34 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/20 5:57:49 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/20 4:31:26 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/20 5:56:42 阅读更多 →

月新闻