鸿蒙ArkUI状态管理全攻略

一、组件内状态(自己用)

1. @State

  • 响应式变量,改了自动刷新 UI
  • 用于:页面显示、开关、计数、列表

2. @Local

  • 非响应式,改了不刷新 UI
  • 用于:临时数据、缓存、中间计算

二、父子组件通信(最常用!高频!)

3. @Prop

父 → 子 单向传递,子不能改

TypeScript 复制代码
@Prop name: string;
  • 父传子,只读

  • 场景:标题、配置、静态数据

  • 在鸿蒙 ArkUI 中,@Prop 装饰器用于建立单向数据同步 :父组件将数据传递给子组件,子组件可以修改自己的 @Prop 副本,但不会自动同步回父组件。如果子组件需要修改父组件的数据,通常有两种方式:

  • 使用 @Link 装饰器(双向同步)

  • 使用回调函数 (通过 @Prop 接收值,再通过事件将修改意图通知父组件)

案例:计数器组件

场景 :父组件维护一个 count 状态,子组件展示该值并提供"增加"按钮,点击后父组件的 count 增加。

1. 子组件(CounterChild.ets)
TypeScript 复制代码
@Component
export struct CounterChild {
  // 接收父组件传入的值(只读)
  @Prop count: number;
  // 定义回调,用于通知父组件增加计数的意图
  onIncrease?: () => void;

  build() {
    Column() {
      Text(`子组件显示计数:${this.count}`)
        .fontSize(20)
        .margin(10)
      Button('增加')
        .onClick(() => {
          // 通过回调通知父组件执行增加操作
          if (this.onIncrease) {
            this.onIncrease();
          }
        })
        .margin(10)
    }
    .width('100%')
    .height(150)
    .backgroundColor('#f0f0f0')
    .borderRadius(8)
  }
}
2. 父组件(ParentPage.ets)
typescript

import { CounterChild } from './CounterChild';

@Entry
@Component
struct ParentPage {
  @State parentCount: number = 0;

  // 子组件触发的回调:修改父组件状态
  private handleIncrease() {
    this.parentCount++;
  }

  build() {
    Column() {
      Text(`父组件计数:${this.parentCount}`)
        .fontSize(24)
        .margin(20)

      // 使用子组件,传递 prop 和回调
      CounterChild({
        count: this.parentCount,
        onIncrease: this.handleIncrease.bind(this)
      })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}
2. 父组件(ParentPage.ets)
TypeScript 复制代码
import { CounterChild } from './CounterChild';

@Entry
@Component
struct ParentPage {
  @State parentCount: number = 0;

  // 子组件触发的回调:修改父组件状态
  private handleIncrease() {
    this.parentCount++;
  }

  build() {
    Column() {
      Text(`父组件计数:${this.parentCount}`)
        .fontSize(24)
        .margin(20)

      // 使用子组件,传递 prop 和回调
      CounterChild({
        count: this.parentCount,
        onIncrease: this.handleIncrease.bind(this) //方法一
        onIncrease: (()=>{  //方法二
           this.handleIncrease()
        })
      })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

关键点说明

这种方式遵循了单向数据流原则,使数据变化来源清晰,便于维护。

  • 父传子,只读

  • 场景:标题、配置、静态数据

  • 在鸿蒙 ArkUI 中,@Prop 装饰器用于建立单向数据同步 :父组件将数据传递给子组件,子组件可以修改自己的 @Prop 副本,但不会自动同步回父组件。如果子组件需要修改父组件的数据,通常有两种方式:

  • 使用回调函数 (通过 @Prop 接收值,再通过事件将修改意图通知父组件)

  • @Prop count 让子组件能显示父组件的值,且子组件内部可以修改该副本(但不会影响父组件)。

  • 子组件通过自定义回调 onIncrease 将修改意图传递给父组件。

  • 父组件在回调中更新 @State parentCount,触发 UI 重新渲染,子组件因 @Prop 接收到新值而同步显示。

父 ↔ 子 双向同步

TypeScript 复制代码
@Link count: number;
  • 子改 = 父也改
  • 场景:开关、表单、弹窗控制

5. @Provide + @Consume

跨多层组件传递(爷 → 孙)

TypeScript 复制代码
// 父/祖先
@Provide("user") user = { name: "张三" }

// 子孙任意层
@Consume("user") user;
  • 不用一层层传
  • 场景:用户信息、主题、全局配置

三、全局应用状态(整个 APP 共享)

6. @AppStorage

全局持久化状态(内存)

TypeScript 复制代码
@AppStorage("token") token: string = "";
  • 所有页面共享
  • 改了所有页面同步刷新

持久化到本地(关机还在)

TypeScript 复制代码
@StorageLink("userId") userId: string = "";
  • 保存在手机本地存储
  • 场景:用户 ID、登录状态、设置

四、UI 渲染 / 性能优化装饰器

8. @Watch

监听状态变化,自动执行函数

TypeScript 复制代码
@Watch("onCountChange")
@State count: number = 0;

onCountChange() {
  console.log("count变了")
}
  • 监听变量,一变就做事
  • 场景:搜索防抖、数据联动

9. @Builder

自定义 UI 块(复用 UI 片段)

TypeScript 复制代码
@Builder
itemTitle(title: string) {
  Text(title).fontSize(20)
}
  • 复用 UI,不用写重复代码

10. @Styles / @Extend

样式复用

TypeScript 复制代码
@Styles
btnStyle() {
  .width(200).height(40)
}

五、生命周期装饰器(构建 / 卸载)

11. @Entry

标记页面入口(只能一个)

12. @Component

标记自定义组件

13. @BuilderParam

组件内传递构建函数


六、最实用总结(背会就能写鸿蒙项目)

数据流动一句话记住:

  • 自己用 → @State(会刷新) / @Local(不刷新)
  • 父传子 → @Prop
  • 父子双向 → @Link
  • 跨多层 → @Provide + @Consume
  • 全局共享 → @AppStorage
  • 本地持久化 → @StorageLink
  • 监听变化 → @Watch
  • 复用 UI → @Builder

七、我给你一个万能速记表(面试直接背)

表格

装饰器 作用 场景
@State 组件内响应式 页面显示数据
@Local 组件内临时变量 缓存 / 计算
@Prop 父→子单向 标题、配置
@Link 父子双向同步 开关、表单
@Provide 祖先跨层传递 用户信息
@Consume 后代跨层接收 页面取值
@AppStorage 全局状态 主题、登录
@StorageLink 本地持久化 用户 ID
@Watch 监听变量变化 搜索、联动
@Builder UI 复用 列表项、按钮
相关推荐
学以智用6 小时前
wangEditor V5 精简完整参考手册
javascript
用户298698530146 小时前
React 前端实现 Excel 与 CSV 互转:基于 WebAssembly 的浏览器端方案
javascript·react.js·excel
1-1=01 天前
Vue 3 模板语
前端·javascript·vue.js
风卿1 天前
看着AI写代码太孤独了,来欣赏星云吧:一个DSH 装饰插件
前端·javascript
牧艺1 天前
弹层不用再手算坐标了:CSS Anchor Positioning 从原理到可上线
前端·javascript·css
愚坤1 天前
前端真有意思,JS还能独立做项目?
前端·javascript·github
李纲明1 天前
微信小程序 getSystemInfo 提示已废弃、屏幕高度算错胶囊还对不齐?getWindowInfo 和 getDeviceInfo 怎么接才稳
javascript·微信小程序·小程序·小程序开发·devdiy
FungLeo1 天前
成为全栈·Vue 管理后台篇·用 fetch 建一层可控的请求内核
前端·javascript·vue.js·http·fetch·formdata·接口封装
用户84298142418101 天前
ByteJS,让重要的 JavaScript 以字节码运行。
javascript
FungLeo1 天前
成为全栈·Vue 管理后台篇·Vue Router如何守住多角色后台边界
前端·javascript·vue.js·rbac·vue router·路由守卫·前端权限