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/24 7:47:27 阅读更多 →
C++23 <stacktrace>库实战:跨平台调试与异常处理新利器

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

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

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

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

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

2026/7/24 9:33:42 阅读更多 →

最新新闻

Unity游戏皮肤定制全流程:从Shader编写到性能优化实战指南

Unity游戏皮肤定制全流程:从Shader编写到性能优化实战指南

1. 项目概述:为什么“皮肤定制”是Unity游戏开发者的必修课? 如果你是一名Unity开发者,或者正在学习Unity,那么“游戏皮肤定制”这个概念你一定不陌生。它听起来简单,不就是换个贴图、改个颜色吗?但当你真正…

2026/7/24 17:24:16 阅读更多 →
终极Windows右键菜单优化指南:5分钟告别卡顿混乱,打造高效工作流

终极Windows右键菜单优化指南:5分钟告别卡顿混乱,打造高效工作流

终极Windows右键菜单优化指南:5分钟告别卡顿混乱,打造高效工作流 【免费下载链接】ContextMenuManager 🖱️ 纯粹的Windows右键菜单管理程序 项目地址: https://gitcode.com/gh_mirrors/co/ContextMenuManager 你是否曾因Windows右键菜…

2026/7/24 17:24:16 阅读更多 →
流式输出的渲染预算:节流与批量提交的工程化治理

流式输出的渲染预算:节流与批量提交的工程化治理

流式输出的渲染预算:节流与批量提交的工程化治理 一、逐 token 渲染的卡顿现场:当 SSE 高频更新撞上虚拟 DOM 大模型流式输出在前端落地,最常见的故障不是网络断流,而是渲染卡顿。SSE 或 ReadableStream 把回答切成 token&#xf…

2026/7/24 17:24:16 阅读更多 →
095、ESP-DL的异常检测案例

095、ESP-DL的异常检测案例

095、ESP-DL的异常检测案例 昨晚调试到凌晨三点,板子上的LED突然开始有规律地闪烁——不是代码里写的那个闪烁模式,而是一种诡异的、像心跳一样的节奏。我盯着逻辑分析仪上的波形看了十分钟,才意识到ESP-DL的异常检测模型真的把那个“异常”抓出来了。这感觉就像你养了一条…

2026/7/24 17:24:16 阅读更多 →
工业级PCB缺陷检测系统:Faster-RCNN实战与优化

工业级PCB缺陷检测系统:Faster-RCNN实战与优化

1. 项目概述:工业级PCB缺陷检测系统实战 去年参与某PCB代工厂的质检系统升级时,我第一次见识到产线上工人用放大镜目检微米级线路的场景。这种传统检测方式不仅效率低下(每块板子平均耗时3分钟),漏检率更是高达15%。这…

2026/7/24 17:24:16 阅读更多 →
一键换背景失效?揭秘Stable Video Diffusion、Runway ML、Pika底层抠像逻辑差异,精准匹配你的硬件配置

一键换背景失效?揭秘Stable Video Diffusion、Runway ML、Pika底层抠像逻辑差异,精准匹配你的硬件配置

更多请点击: https://kaifayun.com 第一章:一键换背景失效?揭秘Stable Video Diffusion、Runway ML、Pika底层抠像逻辑差异,精准匹配你的硬件配置 当“一键换背景”在视频生成工具中突然失效,问题往往不在于UI按钮&am…

2026/7/24 17:23:16 阅读更多 →

日新闻

用Highcharts 创建可拖拽三维散点立方体3D图表

用Highcharts 创建可拖拽三维散点立方体3D图表

该案例基于Highcharts scatter3d 三维散点图实现空间立方体散点可视化,核心特色:三维 X/Y/Z 三轴空间,所有散点分布在 0~10 立方体空间内;散点使用径向渐变实现立体 3D 圆球质感;支持鼠标 / 触屏拖拽画布,…

2026/7/24 0:00:29 阅读更多 →
AppCertDlls:进程创建路径上的 DLL 入口

AppCertDlls:进程创建路径上的 DLL 入口

AppCertDlls:进程创建路径上的 DLL 入口 AppCertDlls 位于 HKLM\System\CurrentControlSet\Control\Session Manager\AppCertDlls。本文的程序功能是只读列出这个键在 64 位和 32 位注册表视图中的全部值,并显示每条值的来源、名称、类型和可安全显示的数…

2026/7/24 0:00:29 阅读更多 →
我的编程之路:第一篇博客

我的编程之路:第一篇博客

大家好,我是一名编程初学者,同时这也是我编程学习之路上的第一篇博客。在这里,我想要向大家介绍我的一些想法和规划。a.自我介绍我是一个刚刚接触编程的新手,目前在学习c语言,我对编程世界充满了强烈的好奇。当然&…

2026/7/24 0:00:29 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/7/23 17:49:47 阅读更多 →

月新闻