鸿蒙ArkUI框架中的状态管理

在ArkUI框架中,状态管理是构建动态应用的核心。以下是组件级别应用级别状态管理装饰器的分类、用途及区别的总结,结合了思考过程中的关键点:

一、组件级别状态管理

1. @State

  • 用途:组件内部私有状态,变化触发UI更新。
  • 示例:按钮的点击状态、计数器数值。
  • 特点:只能初始化一次,单向数据流(组件内修改)。

代码示例

javascript 复制代码
@Component
struct CounterButton {
  @State count: number = 0; // 组件内部状态

  build() {
    Button(`点击次数:${this.count}`)
      .onClick(() => {
        this.count++; // 修改@State变量自动更新UI
      })
  }
}

2. @Prop

  • 用途:父组件向子组件传递数据(单向)。
  • 特点:需通过父组件回调更新数据。
  • 示例:显示父组件传递的文本,子组件不可直接修改。

代码示例

javascript 复制代码
// 父组件
@Component
struct ParentComponent {
  @State parentCount: number = 0;

  build() {
    Column() {
      ChildComponent({ countProp: this.parentCount }) // 传递数据
      Button("父组件增加").onClick(() => this.parentCount++)
    }
  }
}

// 子组件
@Component
struct ChildComponent {
  @Prop countProp: number; // 单向接收父组件数据

  build() {
    Text(`来自父组件的值:${this.countProp}`)
  }
}

  • 用途:父子组件双向数据绑定。
  • 特点 :双向同步,类似Vue的v-model
  • 示例:共享开关状态,子组件直接修改影响父组件。

代码示例

javascript 复制代码
// 父组件
@Component
struct ParentComponent {
  @State sharedCount: number = 0;

  build() {
    Column() {
      ChildComponent({ countLink: $sharedCount }) // 双向绑定
      Text(`父组件值:${this.sharedCount}`)
    }
  }
}

// 子组件
@Component
struct ChildComponent {
  @Link countLink: number; // 双向绑定变量

  build() {
    Button("子组件修改").onClick(() => {
      this.countLink++; // 修改会同步到父组件
    })
  }
}

4. @Provide / @Consume

  • 用途:跨层级组件数据共享(祖先→后代)。
  • 示例:主题颜色全局设置。
  • 特点:避免逐层传递,类似React Context。

代码示例

javascript 复制代码
// 祖先组件
@Component
struct AncestorComponent {
  @Provide themeColor: string = 'blue'; // 提供数据

  build() {
    Column() {
      ChildComponent()
    }
  }
}

// 后代组件
@Component
struct ChildComponent {
  @Consume themeColor: string; // 消费数据

  build() {
    Text(`当前主题色:${this.themeColor}`)
      .fontColor(this.themeColor)
  }
}

  • 用途:观察嵌套对象属性变化。
  • 特点@Observed装饰类,@ObjectLink引用实例。
  • 示例 :用户对象({name: string})属性更新。

代码示例

javascript 复制代码
@Observed // 装饰类
class User {
  name: string;
  age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}

@Component
struct UserProfile {
  @ObjectLink user: User; // 引用被观察对象

  build() {
    Column() {
      Text(`姓名:${this.user.name}`)
      Button("修改年龄").onClick(() => {
        this.user.age++; // 修改会触发UI更新
      })
    }
  }
}

6. @Style

  • 用途:定义可复用的组件样式。
  • 示例:统一按钮样式(颜色、边距)。

代码示例

javascript 复制代码
@Styles function customButtonStyle() {
  .width(120)
  .height(40)
  .backgroundColor(Color.Blue)
  .fontColor(Color.White)
}

@Component
struct StyledButton {
  build() {
    Button("样式按钮")
      .useStyle(customButtonStyle) // 应用样式
  }
}

7. @Builder / @BuilderParam

  • 用途:构建可复用的UI片段或动态插入布局。
  • 示例:自定义卡片布局,父组件传递头部Builder。
  • 区别@Builder定义结构,@BuilderParam接收结构作为参数。

代码示例

javascript 复制代码
@Component
struct CustomCard {
  @BuilderParam header: () => void; // 接收Builder参数

  build() {
    Column() {
      this.header() // 插入自定义头部
      Text("卡片内容...")
    }
  }
}

// 使用组件时传递Builder
CustomCard({
  header: () => {
    Text("自定义标题")
      .fontSize(20)
      .fontColor(Color.Red)
  }
})

8. @Extend

  • 用途:扩展组件样式(如全局字体)。
  • 示例:统一所有文本的字体大小和颜色。

代码示例

javascript 复制代码
@Extend(Text) function boldText() {
  .fontWeight(FontWeight.Bold)
  .fontColor('#333')
}

@Component
struct ExtendedText {
  build() {
    Column() {
      Text("普通文本")
      Text("加粗文本").useStyle(boldText) // 应用扩展样式
    }
  }
}

二、应用级别状态管理

1. @LocalStorage

  • 用途:页面级临时存储(页面关闭后可能保留)。
  • 示例:表单草稿保存。

补充知识点: @LocalStorageProp / @LocalStorageLink

区别:前者单向同步,后者双向绑定页面存储数据。

代码示例

javascript 复制代码
// 页面A
@Entry
@Component
struct PageA {
  @LocalStorage('formData') formData: string = '';

  build() {
    TextInput(this.formData)
      .onChange((value) => {
        this.formData = value; // 数据保存到LocalStorage
      })
  }
}

// 页面B可读取同一LocalStorage
@Component
struct PageB {
  @LocalStorage('formData') formData: string;

  build() {
    Text(`保存的数据:${this.formData}`)
  }
}

2. @AppStorage

  • 用途:全局状态存储(应用生命周期内有效)。
  • 示例:用户登录Token。

补充知识点: @StorageProp / @StorageLink

用途 :绑定到AppStorage中的具体键。

区别@StorageProp单向,@StorageLink双向。

代码示例

javascript 复制代码
// 全局存储用户Token
@AppStorage.setOrCreate('userToken', '') // 初始化

@Component
struct LoginComponent {
  @StorageLink('userToken') token: string; // 双向绑定

  build() {
    Button("登录").onClick(() => {
      this.token = 'abc123'; // 修改全局状态
    })
  }
}

// 其他页面读取
@Component
struct ProfilePage {
  @StorageProp('userToken') token: string; // 单向读取

  build() {
    Text(`Token: ${this.token}`)
  }
}

3. @PersistentStorage

  • 用途:持久化存储(应用重启保留)。
  • 示例:用户偏好设置(语言、主题)。

代码示例

javascript 复制代码
@PersistentStorage.setOrCreate('settings', { theme: 'light', fontSize: 16 })

@Component
struct SettingsPage {
  @StorageLink('theme') theme: string;
  @StorageLink('fontSize') fontSize: number;

  build() {
    Column() {
      Button("切换主题").onClick(() => {
        this.theme = this.theme === 'light' ? 'dark' : 'light';
      })
      Slider({ min: 12, max: 24 })
        .value(this.fontSize)
        .onChange((value) => {
          this.fontSize = value;
        })
    }
  }
}

4. @Environment

  • 用途:访问环境变量(如主题、语言)。
  • 示例:根据系统主题切换应用外观。

代码示例

javascript 复制代码
@Component
struct ThemeAwareComponent {
  @Environment('currentTheme') theme: string;

  build() {
    Text("主题敏感文本")
      .fontColor(this.theme === 'dark' ? Color.White : Color.Black)
      .backgroundColor(this.theme === 'dark' ? Color.Black : Color.White)
  }
}

三、关键区别与选择

  • 作用域

    • 组件级:@State@Prop等用于组件或父子通信。
    • 应用级:@AppStorage@PersistentStorage等跨页面共享。
  • 数据流

    • 单向:@Prop@LocalStorageProp(父→子/存储→组件)。
    • 双向:@Link@LocalStorageLink(父子/组件与存储同步)。
  • 持久性

    • 临时:@State@LocalStorage(页面级)。
    • 持久:@PersistentStorage(设备存储)。
  • 使用场景

    • 简单组件状态 → @State
    • 跨组件共享 → @Provide/@Consume
    • 全局配置 → @AppStorage + @StorageLink
    • 复杂对象监听 → @Observed + @ObjectLink


四、最佳实践总结

  1. 简单交互优先使用@State:适合按钮状态、临时计数等
  2. 父子通信选择@Prop/@Link :单向传递用@Prop,双向同步用@Link
  3. 跨层级共享数据用@Provide/@Consume:避免多级传递的麻烦
  4. 全局状态使用@AppStorage:如用户登录状态、主题配置
  5. 复杂对象监听用@Observed+@ObjectLink:确保嵌套属性变化触发更新
  6. 持久化数据用@PersistentStorage:用户设置、历史记录等需要长期保存的数据

官方文档是更全面的参考:
HarmonyOS ArkUI 文档

相关推荐
别说我什么都不会12 小时前
ohos.net.http请求HttpResponse header中set-ccokie值被转成array类型
网络协议·harmonyos
码是生活12 小时前
鸿蒙开发排坑:解决 resourceManager.getRawFileContent() 获取文件内容为空问题
前端·harmonyos
鸿蒙场景化示例代码技术工程师13 小时前
基于Canvas实现选座功能鸿蒙示例代码
华为·harmonyos
小脑斧爱吃鱼鱼14 小时前
鸿蒙项目笔记(1)
笔记·学习·harmonyos
鸿蒙布道师14 小时前
鸿蒙NEXT开发对象工具类(TS)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
zhang10620914 小时前
HarmonyOS 基础组件和基础布局的介绍
harmonyos·基础组件·基础布局
马剑威(威哥爱编程)15 小时前
在HarmonyOS NEXT 开发中,如何指定一个号码,拉起系统拨号页面
华为·harmonyos·arkts
GeniuswongAir16 小时前
Flutter极速接入IM聊天功能并支持鸿蒙
flutter·华为·harmonyos
别说我什么都不会1 天前
OpenHarmony 5.0(API 12)关系型数据库relationalStore 新增本地数据变化监听接口介绍
api·harmonyos