当前位置: 首页 > news >正文

MoodSelector 心情组件:@Link 双向绑定实现父子通信

前言

在“海风日记“的写日记功能中,心情选择器是核心交互组件之一。用户可以从 5 种心情和 5 种天气中选择,选择结果会实时反映在 UI 上。

MoodSelector组件通过@Link装饰器实现与父组件的双向绑定,子组件修改选择项后,父组件的状态自动更新。本文将从源码出发,深入讲解 @Link 的完整用法。


一、@Link 双向绑定

1.1 子组件定义

@Component export struct MoodSelector { @Link selectedMood: number // 双向绑定心情 @Link selectedWeather: number // 双向绑定天气 build() { Column() { // 心情选项 ForEach(MOOD_OPTIONS, (item, index) => { Text(item.emoji) .onClick(() => { this.selectedMood = index }) }) // 天气选项 ForEach(WEATHER_OPTIONS, (item, index) => { Text(item.emoji) .onClick(() => { this.selectedWeather = index }) }) } } }

1.2 父组件使用

@Entry @Component struct WriteDiaryPage { @State selectedMood: number = 3 // 默认开心 @State selectedWeather: number = 0 // 默认晴天 build() { MoodSelector({ selectedMood: this.selectedMood, // 传入 @State selectedWeather: this.selectedWeather // 传入 @State }) } }

二、心情选项配置

2.1 数据定义

const MOOD_OPTIONS: MoodOption[] = [ { emoji: '😢', label: '难过' }, { emoji: '😕', label: '低落' }, { emoji: '😐', label: '平静' }, { emoji: '🙂', label: '还不错' }, { emoji: '😊', label: '开心' }, ] const WEATHER_OPTIONS: WeatherOption[] = [ { emoji: '☀️', label: '晴' }, { emoji: '⛅', label: '多云' }, { emoji: '🌧️', label: '雨' }, { emoji: '🌬️', label: '大风' }, { emoji: '❄️', label: '雪' }, ]

2.2 心情选择 UI

Row({ space: 8 }) { ForEach(MOOD_OPTIONS, (item: MoodOption, index: number) => { Column({ space: 4 }) { Text(item.emoji) .fontSize(20) .width(40).height(40).textAlign(TextAlign.Center) .borderRadius(20) .backgroundColor( this.selectedMood === index ? 'rgba(255,255,255,0.90)' : 'rgba(255,255,255,0.55)' ) .border({ width: this.selectedMood === index ? 1.5 : 0, color: 'rgba(245,166,35,0.5)' }) .shadow(this.selectedMood === index ? { radius: 8, color: 'rgba(245,166,35,0.25)' } : { radius: 0, color: 'transparent' } ) Text(item.label) .fontSize(9.5) .fontColor(this.selectedMood === index ? '#D4900A' : COLOR_TEXT_HINT) .fontWeight(this.selectedMood === index ? FontWeight.Bold : FontWeight.Normal) } .onClick(() => { this.selectedMood = index }) }) }

三、@State 与 @Link 的对比

3.1 装饰器对比

装饰器数据流向声明位置修改权限
@State内部状态组件内部仅本组件
@Prop父→子(单向)子组件不可同步回父组件
@Link双向绑定子组件可同步回父组件

3.2 选择指南

  • 子组件需要修改父组件数据 → 使用@Link
  • 子组件只展示父组件数据 → 使用@Prop或普通属性
  • 数据只在组件内部使用→ 使用@State

四、天气选择 UI

Row({ space: 8 }) { ForEach(WEATHER_OPTIONS, (item: WeatherOption, index: number) => { Row({ space: 4 }) { Text(item.emoji).fontSize(12) Text(item.label).fontSize(12) .fontColor(this.selectedWeather === index ? '#C8800A' : COLOR_AMBER) .fontWeight(this.selectedWeather === index ? FontWeight.Bold : FontWeight.Normal) } .padding({ left: 10, right: 10, top: 5, bottom: 5 }) .borderRadius(14) .backgroundColor( this.selectedWeather === index ? 'rgba(255,255,255,0.85)' : 'rgba(255,255,255,0.45)' ) .border({ width: 1, color: this.selectedWeather === index ? 'rgba(245,166,35,0.35)' : 'rgba(245,166,35,0.15)' }) .onClick(() => { this.selectedWeather = index }) }) }

五、完整组件布局

Column({ space: 0 }) { // 心情选择 Text('今天的心情') .fontSize(11).fontColor(COLOR_AMBER).fontWeight(FontWeight.Medium) .margin({ bottom: 8 }) // 心情 Row this.moodRow() // 天气 Row this.weatherRow() } .width('100%') .alignItems(HorizontalAlign.Start)

六、常见问题与排查

6.1 @Link 绑定失败

问题:子组件修改了@Link变量,但父组件 UI 没有更新。

原因:父组件传入的值不是@State变量。

解决方案:确保父组件传入的是@State变量。

6.2 选中态不显示

问题:点击心情选项后选中状态没有变化。

原因@Link绑定成功但 UI 判断逻辑有误。

解决方案:检查selectedMood === index的比较逻辑。


总结

本文通过“海风日记“的 MoodSelector 组件,深入讲解了 @Link 双向绑定的用法:

  1. @Link 装饰器:子组件中定义,与父组件 @State 双向绑定
  2. 心情选项:5 种心情的 emoji 和标签
  3. 天气选项:5 种天气的 emoji 和标签
  4. 选中态样式:背景色、边框、阴影的条件切换
  5. @State vs @Link:不同装饰器的选择策略

下一篇文章将深入讲解TextInput 与 TextArea输入框的优化体验,敬请期待。

如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!


相关资源:

  • @Link 装饰器文档
  • @State 装饰器文档
  • @Prop 装饰器文档
  • 海风日记项目源码
  • [HarmonyOS 开发者官网](https://atomgit.com/openharmony/docs
  • 开源鸿蒙跨平台社区
http://www.cnnetsun.cn/news/3528043.html

相关文章:

  • 无限画布制作沙发换装视频,太有创意了!
  • Android RecyclerView核心原理与优化实践
  • WINCE系统启动自动运行程序的实现方案
  • Python元类:类的构造者
  • 除了image和NGS-base,也许空间转录组平台该按分辨率划分:单细胞、亚细胞、多细胞
  • 从零掌握Locust:Python分布式性能测试实战指南
  • Android定时任务:Handler与Timer的深度对比与实践
  • Agent开发的难点是什么呢?
  • NCF实战:工业级神经协同过滤从零落地指南
  • 深入解析UART/IrDA/CIR控制器寄存器:从配置到多模式通信实战
  • 【单片机毕业设计】基于 51/STM32 单片机的车载酒精检测与发动机断电预警系统设计,基于 51/STM32 单片机的 MQ-3 酒精浓度声光语音报警装置开发(020502)
  • 【Bug已解决】Codex Desktop: project rename dialog closes when sidebar auto-hides in hover mode 解决方案
  • 2026年语音识别平台哪个好?这3个实用选择标准帮你挑到合适的
  • TI微控制器GPTM定时器寄存器级配置与PWM应用实战
  • Android代码混淆与优化:ProGuard/R8实战指南
  • Windows 7用户获取Chrome最终版指南与安全建议
  • 嵌入式系统底层开发:SCM寄存器与MMU内存管理实战解析
  • 合并K个有序链表的高效解法
  • AM62L DSS寄存器配置实战:从时序到透明控制的嵌入式显示开发指南
  • GRPC拦截器全套封装:鉴权、限流、日志追踪、异常统一处理,企业级通用拦截器模板
  • 深入解析TI OMAP3 IVA2.2子系统:MMU配置与视频序列器实战指南
  • 嵌入式系统I/O引脚配置与电源优化:以OMAP34xx SCM模块为例
  • 嵌入式低功耗与精准定时:SysCtrl与GPTimer协同设计实战
  • AI+企业数字化行业解决方案(1):企业售前方案生成Agent怎么设计?
  • Unity场景程序化生成实战:GeNa 2核心功能与性能优化全解析
  • K-means面试深度解析:原理、初始化陷阱与工程静默规则
  • 【Bug已解决】Codex capacity errors 自动重试与意图保留 解决方案
  • 深入解析AM62L DSS中断与安全寄存器:从原理到嵌入式显示驱动实战
  • CHPDA高速数据采集系统:微秒级工业实时数据分析实践指南
  • 构建高效Web笔记系统的核心技术与实践