发布时间:2026/7/31 2:51:44
ArkTS 进阶之道(20):@Link 跨组件双向同步边界——父改子同步+子改父同步为啥要 $ 语法 ArkTS 进阶之道20Link 跨组件双向同步边界——父改子同步子改父同步为啥要 $ 语法本文是「ArkTS 进阶之道」系列第 20 篇续「ArkUI 状态联动」深水区篇 68 开篇。上篇讲 Watch 状态监听边界Watch 绑 State 变触发副作用回调槽。本文讲跨组件双向同步边界Link 荬饰器父改子同步子改父同步双向——根因在 $ 语法双向绑定不是单向传值Link 父改子同步子改父同步双向Prop 父改子同步单向子改父不同步。能力系列篇 20 讲过 Link 怎么用本文讲为哈 Link 双向同步合法 Prop 单向同步子改父不同步——根因在 $ 语法双向绑定。一、开篇Link 不是单向传值是 $ 语法双向绑定的跨组件同步你写 React 时父子组件状态同步是「回调魔法」父传 props 子改父调回调// React 父子组件状态同步父传 props 子改父调回调 function Parent() { const [count, setCount] useState(0) return Child count{count} onCountChange{setCount} / // 父传 props 回调 } function Child({ count, onCountChange }) { return button onClick{() onCountChange(count 1)}子改 count{count}/button } // React 父子同步父传 props 子改父调回调回调魔法你写鸿蒙 ArkTS 时Link$ 语法双向绑定——父改子同步子改父同步双向// ArkTS Link $ 语法双向绑定 Entry Component struct Index { State linkCount: number 0 // ✅ 父 State linkCount build() { Column() { ChildLink({ childCount: $linkCount }) // ✅ $ 语法双向绑定父改子同步子改父同步 } } } Component struct ChildLink { Link childCount: number // ✅ Link 子 childCount 双向同步父 State linkCount build() { Button(子改 childCount${this.childCount}) .onClick(() { this.childCount }) // ✅ 子改 childCount → 父 State linkCount 同步 } } // Link $ 语法双向绑定父改子同步子改父同步双向回调魔法 vs $ 语法双向绑定的区别React 把父子同步当回调魔法父传 props 子改父调回调ArkTS 把 Link 当「$ 语法双向绑定荬饰器」父改子同步子改父同步双向。根因不是回调魔法是 $ 语法双向绑定——Link $ 语法编译期绑父子双向同步槽父改子同步子改父同步双向。二、根因Link 的 $ 语法双向绑定机制鸿蒙 ArkUI 的 Link 是**$ 语法双向绑定**——编译期把 Link 绑成父子双向同步槽父改子同步子改父同步双向来自三重绑定机制。机制 1Link $ 语法编译期绑父子双向同步槽——不是单向传值Link 荬饰器 $ 语法编译期绑父子双向同步槽——把 $linkCount 绑成父子双向同步槽父改子同步子改父同步双向Entry Component struct Index { State linkCount: number 0 // ✅ 父 State linkCount build() { Column() { ChildLink({ childCount: $linkCount }) // ✅ $ 语法双向绑定编译期绑父子双向同步槽 } } } Component struct ChildLink { Link childCount: number // ✅ Link 子 childCount 双向同步父 State linkCount build() { Column() { Text(childCount ${this.childCount}) Button(子改 childCountLink 子改父同步) .onClick(() { this.childCount }) // ✅ 子改 childCount → 父 State linkCount 同步 } } } // 编译期$linkCount 绑成父子双向同步槽父 State linkCount ↔ 子 Link childCount // 运行时父改 linkCount → 子 childCount 同步 子改 childCount → 父 linkCount 同步双向编译期绑父子双向同步槽Link $ 语法编译期把$linkCount绑成父子双向同步槽——父State linkCount↔ 子Link childCount双向同步。父改linkCount→ 子childCount同步子改childCount→ 父linkCount同步双向。根因不是单向传值是 $ 语法双向绑定。机制 2Prop 单向同步——父改子同步子改父不同步无 $ 语法Prop 荬饰器单向同步——父改子同步子改父不同步无 $ 语法子只改本地副本Entry Component struct Index { State propCount: number 0 // ⚠ 父 State propCount build() { Column() { ChildProp({ childCount: this.propCount }) // ⚠ Prop 单向同步无 $ 语法传值副本 } } } Component struct ChildProp { Prop childCount: number // ⚠ Prop 单向同步父改 childCount 子同步 子改 childCount 父不同步 build() { Column() { Text(childCount ${this.childCount}) Button(子改 childCountProp 子改父不同步) .onClick(() { this.childCount }) // ⚠ Prop 子改 childCount → 父 State childCount 不同步只改子本地副本 } } } // Prop 单向同步父改 propCount → 子 childCount 同步 子改 childCount → 父 propCount 不同步只改子本地副本Prop 单向同步Prop 无 $ 语法单向同步——父改propCount→ 子childCount同步子改childCount→ 父propCount不同步只改子本地副本。根因不是双向同步是单向传值副本——Prop 子只改本地副本不回传父。机制 3Link $ 语法 vs Prop 传值边界——双向同步 vs 单向传值Link$ 语法双向同步父改子同步子改父同步双向Prop传值单向同步父改子同步子改父不同步单向——根因都是父子同步但绑的机制不同Entry Component struct Index { State linkCount: number 0 // ✅ Link 父状态父改子同步 子改父同步双向 State propCount: number 0 // ⚠ Prop 父状态父改子同步单向子改父不同步 build() { Column() { // ✅ Link 路径$ 语法双向绑定父改子同步子改父同步双向 ChildLink({ childCount: $linkCount }) // ⚠ Prop 路径传值单向同步父改子同步子改父不同步单向 ChildProp({ childCount: this.propCount }) } } } // Link $ 语法双向绑定父改 linkCount → 子 childCount 同步 子改 childCount → 父 linkCount 同步双向 // Prop 传值单向同步父改 propCount → 子 childCount 同步 子改 childCount → 父 propCount 不同步单向Link $ 语法 vs Prop 传值边界Link 路径——$ 语法双向绑定父改子同步子改父同步双向推荐。Prop 路径——传值单向同步父改子同步子改父不同步单向子改只改本地副本。根因都是父子同步但绑的机制不同——Link $ 语法双向绑定双向同步槽Prop 传值单向同步单向传值副本。机制 4Link $ 语法必须配 State——不能配普通变量Link$ 语法必须配 State——$ 语法双向绑定要求父状态是 State响应式不能配普通变量Entry Component struct Index { State linkCount: number 0 // ✅ State 配 Link $ 语法双向绑定 private normalCount: number 0 // ❌ 普通变量不能配 Link $ 语法无响应式 build() { Column() { // ✅ Link $ 语法配 State双向同步合法 ChildLink({ childCount: $linkCount }) // ❌ Link $ 语法配普通变量编译报错$ 语法要求 State 响应式 // ChildLink({ childCount: $normalCount }) // ❌ 编译报错 } } } // Link $ 语法必须配 State$ 语法双向绑定要求父状态是 State响应式 // 普通变量无响应式不能配 Link $ 语法编译报错Link $ 语法必须配 StateLink $ 语法双向绑定要求父状态是 State响应式普通变量无响应式不能配 Link $ 语法编译报错。根因不是任意变量是 State 响应式——Link $ 语法双向同步槽要求父 State 响应式才能双向同步。三、真机配图Link 跨组件双向同步边界——$ 语法双向绑定初始态父 linkCount0、父 propCount0、两子组件 childCount0 均双向同步边界初始值点调四按钮后父 linkCount1 子 ChildLink childCount1 父子都同步、父 propCount1 子 ChildProp childCount1 父同步但子改后父 propCount 仍1 不同步均双向同步边界对比证据齐对比证据点父改 linkCount 后子 ChildLink childCount 同步父改子同步点子改 ChildLink childCount 后父 linkCount 同步子改父同步双向。点父改 propCount 后子 ChildProp childCount 同步父改子同步点子改 ChildProp childCount 后父 propCount 仍1 不同步子改父不同步单向。Link $ 语法双向绑定父改子同步子改父同步双向vs Prop 传值单向同步父改子同步子改父不同步单向——Link 荬饰器 $ 语法编译期绑父子双向同步槽Prop 传值单向同步子改只改本地副本。四、真解法Link 跨组件双向同步的三个场景场景 1Link 父子计数器双向同步90% 场景首选$ 语法双向绑定Entry Component struct Index { State count: number 0 // ✅ 父 State count build() { Column() { Text(父 count ${this.count}) ChildCounter({ childCount: $count }) // ✅ $ 语法双向绑定 } } } Component struct ChildCounter { Link childCount: number // ✅ Link 子 childCount 双向同步父 State count build() { Column() { Text(子 childCount ${this.childCount}) Button(子改 childCount) .onClick(() { this.childCount }) // ✅ 子改 childCount → 父 State count 同步 } } }为哈能跑Link 父子计数器双向同步——$ 语法双向绑定父改 count → 子 childCount 同步 子改 childCount → 父 count 同步双向。首选这个90% 的场景父子组件状态双向同步用 Link $ 语法双向绑定就够。要写「父子组件状态双向同步计数器等」时用这个——不用 Prop 单向同步子改父不同步Link $ 语法双向绑定父子都同步。场景 2Link 父子表单双向同步$ 语法双向绑定子改父同步Entry Component struct Index { State name: string // ✅ 父 State name build() { Column() { Text(父 name ${this.name}) ChildInput({ childName: $name }) // ✅ $ 语法双向绑定 } } } Component struct ChildInput { Link childName: string // ✅ Link 子 childName 双向同步父 State name build() { TextInput({ text: this.childName, placeholder: 输入姓名 }) .onChange((value: string) { this.childName value }) // ✅ 子改 childName → 父 State name 同步 } } // Link 父子表单双向同步子 Input 改 childName → 父 State name 同步子改父同步双向 // 不用 Prop 单向同步子改父不同步Link $ 语法双向绑定父子都同步为哈能跑Link 父子表单双向同步——$ 语法双向绑定子 Input 改childName→ 父State name同步子改父同步双向。要写「父子表单双向同步Input 改子父同步等」时用这个——不用 Prop 单向同步子改父不同步Link $ 语法双向绑定父子都同步。场景 3Link 父子对象双向同步$ 语法双向绑定对象引用同步interface User { name: string; age: number } Entry Component struct Index { State user: User { name: 张三, age: 25 } // ✅ 父 State user 对象 build() { Column() { Text(父 user ${JSON.stringify(this.user)}) ChildUser({ childUser: $user }) // ✅ $ 语法双向绑定对象 } } } Component struct ChildUser { Link childUser: User // ✅ Link 子 childUser 双向同步父 State user 对象 build() { Column() { TextInput({ text: this.childUser.name, placeholder: 姓名 }) .onChange((value: string) { this.childUser.name value }) // ✅ 子改 childUser.name → 父 State user.name 同步 Button(子改 age) .onClick(() { this.childUser.age }) // ✅ 子改 childUser.age → 父 State user.age 同步 } } } // Link 父子对象双向同步$ 语法双向绑定对象引用子改 childUser.name/age → 父 State user.name/age 同步双向 // 对象引用同步Link 绑对象引用子改对象属性父同步不用深拷贝为哈能跑Link 父子对象双向同步——$ 语法双向绑定对象引用子改childUser.name/age→ 父State user.name/age同步双向。要写「父子对象双向同步对象属性改父子都同步等」时用这个——不用 Prop 单向同步子改对象属性父不同步Link $ 语法双向绑定对象引用父子都同步。五、一句话哲学Link 不是单向传值是 $ 语法双向绑定的跨组件同步。ArkUI 的 Link 荬饰器 $ 语法编译期绑父子双向同步槽父改子同步子改父同步双向。根因不是单向传值是 $ 语法双向绑定——Link $ 语法编译期绑父子双向同步槽父 State ↔ 子 Link 双向同步 Prop 传值单向同步父改子同步子改父不同步子改只改本地副本 Link $ 语法必须配 State$ 语法双向绑定要求父 State 响应式 Link $ 语法 vs Prop 传值边界双向同步 vs 单向传值。对比 React 父子组件状态同步回调魔法父传 props 子改父调回调ArkTS Link $ 语法双向绑定父子都同步。状态联动深水区串讲Watch 绑 State 变触发副作用回调槽篇 68onClick 改 State 不直接调副作用单向数据流 Link $ 语法双向绑定跨组件同步篇 69父改子同步子改父同步双向——续「ArkUI 状态联动」深水区讲状态联动深水区Watch 副作用回调槽边界 Link $ 语法双向绑定边界。系列预告下篇篇 70讲 Provide/Consume 跨层级传递边界祖辈 Provide 后辈 Consume 跨层级传递根因续「ArkUI 状态联动」深水区。五阶段哲学体系类型哲学50-52→ 作用域哲学53-55→ 状态哲学56-59→ 渎染哲学60-62→ 组件设计63-67→ 状态联动深水区68讲清 ArkTS/ArkUI 进阶哲学。能力系列回链能力系列篇本文进阶点篇 20 Link 用法Link $ 语法双向绑定边界根因父改子同步子改父同步双向篇 13 State 基础用法状态哲学State 赋值就刷 UI 依赖追踪篇 59 Watch 用法状态联动深水区Watch 副作用回调槽 vs onClick 直接调副作用边界真机 demo 完整代码// 篇 69 demoLink 跨组件双向同步边界——父改子同步 子改父同步双向 // 对比Link 双向同步父改子子改父都同步vs Prop 单向同步父改子同步子改父不同步 // ✅ 子组件Link 双向同步——父改子同步 子改父同步 Component struct ChildLink { Link childCount: number // ✅ Link 双向同步父改 childCount 子同步 子改 childCount 父同步 build() { Column({ space: 8 }) { Text(子组件 ChildLinkLink 双向同步) .fontSize(13).fontColor(#2563eb).fontWeight(FontWeight.Bold) Text(childCount ${this.childCount}) .fontSize(16).fontWeight(FontWeight.Bold) Button(子改 childCountLink 子改父同步) .width(92%).height(40).fontSize(12) .onClick(() { this.childCount // ✅ Link 子改 childCount → 父 State childCount 同步 }) } .width(92%).padding(10).backgroundColor(#e0f0ff).borderRadius(8) } } // ⚠ 对比组件Prop 单向同步——父改子同步 子改父不同步Prop 子改不回传父 Component struct ChildProp { Prop childCount: number // ⚠ Prop 单向同步父改 childCount 子同步 子改 childCount 父不同步 build() { Column({ space: 8 }) { Text(对比组件 ChildPropProp 单向同步) .fontSize(13).fontColor(#ff6600).fontWeight(FontWeight.Bold) Text(childCount ${this.childCount}) .fontSize(16).fontWeight(FontWeight.Bold) Button(子改 childCountProp 子改父不同步) .width(92%).height(40).fontSize(12) .onClick(() { this.childCount // ⚠ Prop 子改 childCount → 父 State childCount 不同步只改子本地副本 }) } .width(92%).padding(10).backgroundColor(#fff0e0).borderRadius(8) } } Entry Component struct Index { State linkCount: number 0 // ✅ Link 父状态父改子同步 子改父同步双向 State propCount: number 0 // ⚠ Prop 父状态父改子同步单向子改父不同步 State log: string (未操作) build() { Column({ space: 12 }) { Text(篇 69 配图Link 跨组件双向同步边界) .fontSize(18).fontWeight(FontWeight.Bold).margin({ top: 20, bottom: 8 }) Text(Link 双向同步父改子子改父都同步vs Prop 单向同步父改子同步子改父不同步) .fontSize(11).fontColor(#888).margin({ bottom: 12 }) // ✅ Link 路径父改 linkCount → 子 Link 同步 子改 childCount → 父 State 同步 Column({ space: 6 }) { Text(父 linkCount ${this.linkCount}).fontSize(14).fontWeight(FontWeight.Bold).fontColor(#2563eb) Button(父改 linkCountLink 父改子同步) .width(92%).height(40).fontSize(12) .onClick(() { this.linkCount // ✅ Link 父改 linkCount → 子 Link childCount 同步 this.log 父改 linkCount${this.linkCount}Link 父改子同步 }) ChildLink({ childCount: $linkCount }) // ✅ Link $ 语法双向绑定 } .width(92%).padding(10).backgroundColor(#f5f5f5).borderRadius(8) // ⚠ Prop 路径父改 propCount → 子 Prop 同步 子改 childCount → 父 State 不同步 Column({ space: 6 }) { Text(父 propCount ${this.propCount}).fontSize(14).fontWeight(FontWeight.Bold).fontColor(#ff6600) Button(父改 propCountProp 父改子同步) .width(92%).height(40).fontSize(12) .onClick(() { this.propCount // ✅ Prop 父改 propCount → 子 Prop childCount 同步 this.log 父改 propCount${this.propCount}Prop 父改子同步 }) ChildProp({ childCount: this.propCount }) // ⚠ Prop 单向同步无 $ 语法 } .width(92%).padding(10).backgroundColor(#f5f5f5).borderRadius(8) Text(日志${this.log}).fontSize(11).fontColor(#333).margin({ top: 4 }) } .width(100%).height(100%).alignItems(HorizontalAlign.Center) } }写鸿蒙 ArkUI 记住Link 不是单向传值是 $ 语法双向绑定的跨组件同步——Link 荬饰器 $ 语法编译期绑父子双向同步槽父改子同步子改父同步双向。根因不是单向传值是 $ 语法双向绑定——Link $ 语法编译期绑父子双向同步槽父 State ↔ 子 Link 双向同步 Prop 传值单向同步父改子同步子改父不同步子改只改本地副本 Link $ 语法必须配 State$ 语法双向绑定要求父 State 响应式 Link $ 语法 vs Prop 传值边界双向同步 vs 单向传值。Link 父子计数器双向同步用 $ 语法双向绑定首选90% 场景Link 父子表单双向同步用 $ 语法双向绑定子改父同步Link 父子对象双向同步用 $ 语法双向绑定对象引用同步。$ 语法双向绑定父子都同步是 ArkUI 状态联动深水区核心

相关新闻

2026/7/31 2:46:43

Modbus RTU协议详解:从原理到实战的工业通信指南

1. 项目概述:从工业现场到数字世界的桥梁在工业自动化、楼宇自控、能源管理这些领域里,我们常常需要让一堆“哑巴”设备开口说话,把温度、压力、开关状态这些物理信号,变成计算机能理解、能处理的数据。这个“翻译”工作&#xff…

2026/7/31 2:46:43

五子棋游戏开发:从设计到实现的全流程解析

1. 五子棋系统设计概述五子棋作为一款经典的双人策略型棋类游戏,其电子化实现涉及多个技术模块的协同工作。这个设计报告完整呈现了从需求分析到最终实现的完整开发流程,包含可运行的源码、详细设计文档和配套讲解资料。整套方案不仅实现了基础的对弈功能…

2026/7/31 3:56:47

OpenClaw安装方法2026,最简单的部署方式推荐

折腾了半天才发现,OpenClaw安装其实没那么玄乎 说实话,我第一次接触OpenClaw的时候,真的被各路教程给整懵了。有的说要配复杂的环境变量,有的要改Nginx配置,还有的动不动就让你编译源码……我电脑小白一个&#xff0c…

2026/7/31 3:56:47

基于eNSP的企业级网络综合实验:从VLAN、OSPF到NAT与ACL全配置

1. 项目概述:从零到一构建企业级模拟网络最近在带新人,发现很多刚接触网络技术的朋友,一听到“综合网配置”就有点发怵,觉得这玩意儿肯定复杂得要命。其实,它更像是在玩一个高自由度的“数字乐高”——给你一堆虚拟的华…

2026/7/31 3:56:47

STM32数码管驱动实战:74HC595动态扫描原理与避坑指南

1. 项目缘起与核心价值最近在整理过往的嵌入式项目资料,翻到了当年备赛蓝桥杯嵌入式竞赛时,关于数码管驱动的那一堆代码和笔记。说实话,当时为了搞定那几块数码管,特别是用74HC595这种串行芯片去驱动,没少走弯路。网上…

2026/7/31 3:56:47

深入理解STM32系统架构与时钟树:从总线矩阵到时钟配置实战

1. 项目概述:从“点灯”到“架构”的认知跃迁很多朋友刚开始接触STM32,都是从点亮一个LED灯开始的。用HAL库或者标准库,几行代码,一个GPIO口置高置低,灯就闪起来了。这当然没问题,但当你开始做更复杂的项目…

2026/7/31 3:51:47

norflash.h

/******************************************************************************************************* file norflash.h* author 正点原子团队(ALIENTEK)* version V1.0* date 2020-04-24* brief NOR FLASH(25QXX) 驱动代码* license …

2026/7/29 22:32:30

PDF合并与动态水印的工程化方案:2026国内免费工具实测对比

一、背景与测试方案 在实际项目交付中,PDF文件合并与版权保护水印的叠加是一个高频但容易被低估的技术需求。典型的处理链路涉及:多源PDF的文件流合并、页面级水印渲染(含透明度混合与图层叠加)、输出文件体积控制。看似简单的操作…

2026/7/31 0:01:11

物理复制比逻辑复制好在哪?数据库复制原理详解

数据库复制是把主库数据同步到备库的机制,分为逻辑复制和物理复制两种。逻辑复制传输的是 SQL 语句或行变更事件,物理复制传输的是存储引擎底层的物理日志。阿里云 PolarDB(云原生数据库)采用物理复制,在同步延迟、数据…

2026/7/31 0:01:11

BilibiliDown:3分钟学会B站视频下载的终极指南

BilibiliDown:3分钟学会B站视频下载的终极指南 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader 😳 项目地址: https://gitcode.com/gh_mirrors/bi/Bilib…

2026/7/31 0:01:11

有哪些游戏数据AI平台?游戏行业Data+AI融合方案盘点

当前,游戏行业的“DataAI融合”已从概念验证进入价值落地阶段。根据IDC 2025年数据,中国AI游戏云市场规模已达18.6亿元;同时,游戏研发环节AI渗透率高达86%,生成式AI内容普及率超过50%。面对庞大的市场,游戏…

2026/7/31 0:38:56

3个高效策略:快速掌握Axure中文界面配置

3个高效策略:快速掌握Axure中文界面配置 【免费下载链接】axure-cn Chinese language file for Axure RP. Axure RP 简体中文语言包。支持 Axure 11、10、9。不定期更新。 项目地址: https://gitcode.com/gh_mirrors/ax/axure-cn 还在为Axure RP的英文界面感…