鸿蒙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 复用 列表项、按钮
相关推荐
Highcharts.js2 小时前
Highcharts Grid Lite:企业免费表格数据的基本工具
前端·javascript·信息可视化·免费·highcharts·表格工具
程序员小李白2 小时前
Vue 组件通信 极简速记版
前端·javascript·vue.js
英俊潇洒美少年2 小时前
React 16 → 17 → 18 → 19 完整区别
前端·javascript·react.js
专注VB编程开发20年2 小时前
Typescript就像C#,VS IDE以前对JS只有基础、弱智能的支持
javascript·vscode·microsoft·typescript
533_2 小时前
[vxe-table el-tree] 树表格:选中子节点,父节点无影响;选中父节点,子节点被选中,el-tree也同理
前端·javascript·vue.js
阳光雨滴2 小时前
树级结构部门选择和人员选择联动功能处理
javascript·vue.js·elementui
英俊潇洒美少年2 小时前
Vue2 和 Vue3 所有区别
前端·javascript·vue.js
书到用时方恨少!2 小时前
基于 Three.js 的 3D 地球可视化项目
开发语言·javascript·3d
一个写bug的人2 小时前
elementui中表格的表头固定 侧边列表固定 滚动条在头部 且使用鼠标滚轮横向时 可同步给顶部滚动条
前端·javascript·elementui