news 2026/7/19 21:53:52

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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
  • 开源鸿蒙跨平台社区
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/19 21:51:36

无限画布制作沙发换装视频,太有创意了!

有时,我在有空的时候打开手机,刷了一条又一条女装带货短视频,几个小时一顿操作下来,停下来回想了下,嗯嗯~,看了这么久,刚才我在干嘛?是的,感觉什么都不记得了&#xff0c…

作者头像 李华
网站建设 2026/7/19 21:47:36

Android RecyclerView核心原理与优化实践

1. RecyclerView的核心价值与适用场景 在Android开发中,列表视图是最常见的UI组件之一。传统ListView虽然简单易用,但在处理大数据集时存在明显的性能瓶颈。2014年Google I/O大会上推出的RecyclerView,通过创新的视图回收机制彻底改变了这一局…

作者头像 李华
网站建设 2026/7/19 21:47:27

WINCE系统启动自动运行程序的实现方案

1. WINCE系统启动自动运行程序的背景与需求 在工业控制、嵌入式设备和专用终端领域,Windows CE(简称WINCE)系统因其轻量化和高度可定制性而广受欢迎。不同于桌面版Windows系统,WINCE通常需要实现开机后自动运行特定应用程序的功能…

作者头像 李华
网站建设 2026/7/19 21:37:55

Python元类:类的构造者

Python中,类本身也是对象——这个事实在元类层面被推向极致。如果类是创建对象的模板,那么元类就是创建类的模板。 一、type:动态创建类的函数 type函数有两种用法。最常见的是用于检查对象的类型,另一个是动态创建类。 type(na…

作者头像 李华
网站建设 2026/7/19 21:36:26

从零掌握Locust:Python分布式性能测试实战指南

1. 项目概述:为什么选择Locust作为压测工具? 在软件开发和运维的日常工作中,性能测试是保障系统稳定性的关键一环。无论是上线前的容量评估,还是线上突发流量时的瓶颈定位,一个趁手的压测工具都至关重要。市面上工具不…

作者头像 李华