适用版本:HarmonyOS NEXT / API 12+ / ArkTS / Stage模型
阅读对象:HarmonyOS初学者、ArkUI开发者、中高级开发工程师
预计阅读时间:60~90分钟


前言

学习 HarmonyOS ArkUI 时,第一个接触的状态管理装饰器几乎都是:


@State

几乎所有官方 Demo 都是这样开始的:


@Entry
@Component
struct Index {

  @State count: number = 0

  build() {
    Column() {
      Text(`${this.count}`)

      Button("增加")
        .onClick(() => {
          this.count++
        })
    }
  }
}

很多开发者会认为:

@State 就是一个变量。

事实上完全不是。

真正发生的是:


修改变量
      │
      ▼
ArkUI状态系统监听
      │
      ▼
标记Dirty
      │
      ▼
Scheduler加入刷新队列
      │
      ▼
重新Build()
      │
      ▼
Diff算法
      │
      ▼
更新UI节点

也就是说:

@State真正的作用不是保存数据,而是通知UI刷新。

本文将从:

  • @State设计目的
  • 编译器原理
  • 响应式机制
  • Dirty标记
  • Build刷新
  • Diff算法
  • 生命周期
  • Observer机制
  • 性能优化
  • 与Vue/React区别
  • 与Observed关系
  • 与ObjectLink关系
  • 底层源码思想

彻底讲透 HarmonyOS 中 @State。


第一章 什么是 @State?

官方定义:

@State 是组件内部状态。

它具有三个特点:

  • 私有
  • 可响应
  • 自动刷新UI

例如:


@State message: string = "Hello"

页面:


Text(this.message)

修改:


this.message = "HarmonyOS"

页面立即刷新。

所以:


State
=
数据
+
监听
+
刷新

而不是:


普通变量

第二章 为什么需要 @State?

假设没有状态管理。

例如:


let count = 0

页面:


Text(`${count}`)

按钮:


count++

UI不会刷新。

为什么?

因为:

ArkUI不知道:


count变了

所以不会:


重新Build

因此需要:


State

告诉框架:


我发生变化了。

第三章 普通变量和 @State 区别

普通变量:


count++

仅仅修改内存。

不会通知任何人。

而:


@State count

实际上是:


Setter
↓

通知框架

↓

UI刷新

所以:


State
≈
Observable

第四章 一个完整刷新过程

例如:


Button("Add")

点击:


this.count++

实际上经历:


count++

↓

Setter

↓

StateObject

↓

NotifyChange()

↓

Component Dirty

↓

Scheduler

↓

Build()

↓

Diff

↓

Render

整个过程几十微秒完成。


第五章 编译器如何处理 @State?

开发者写:


@State
count = 0

编译后不会还是这样。

编译器大概生成:


private __count =
new ObservedPropertySimplePU(
    0,
    this,
    "count"
)

真正访问:


get count() {
    return this.__count.get()
}

set count(v) {
    this.__count.set(v)
}

所以:

开发者写:


count++

真正执行:


get()

+

set()

因此:

框架知道:


发生修改

第六章 Setter 做了什么?

Setter里面主要四件事。

第一步:

保存数据:


value = newValue

第二步:

判断是否变化:


old != new

第三步:

通知观察者:


notify()

第四步:

组件Dirty。

最终:


等待下一帧刷新

第七章 为什么不能直接修改对象属性?

例如:


@State
user = {
    name:"Tom"
}

修改:


this.user.name = "Jack"

很多新人发现:

UI没有刷新。

为什么?

因为:

State监听的是:


user引用

不是:


user.name

所以:

Setter根本没调用。

正确方式:


this.user = {
    ...this.user,
    name:"Jack"
}

引用变化:


Setter执行

页面刷新。


第八章 为什么数组 push 有时候刷新?

例如:


@State
list = []

执行:


list.push(1)

HarmonyOS 5 中:

数组进行了增强代理。

因此:


push()

↓

通知State

↓

刷新

而:

普通对象:


obj.name="xx"

不会。

所以:

数组和对象机制不同。


第九章 @State 生命周期

组件创建:


Create Component

↓

Create State

↓

注册Observer

↓

第一次Build

组件销毁:


Destroy

↓

解绑Observer

↓

释放State

因此:

State生命周期:


跟组件一致。

第十章 Build 为什么会重新执行?

很多人误以为:


刷新Text

实际上:

ArkUI重新执行:


build()

例如:


build(){

Text(this.count)

Button()
}

count改变:

重新执行:


build()

不是:

重新执行:


Button点击事件

只有:


build()

重新跑。


第十一章 为什么不会整页刷新?

有人担心:


build重新执行

是不是整个页面都重新创建?

答案:

不是。

因为:

后面还有:


Diff

例如:

旧:


Text 10
Button
Image

新:


Text 11
Button
Image

Diff结果:


仅更新Text

Button:


保持原对象

Image:


保持原对象

所以性能非常高。


第十二章 Dirty 标记机制

State修改:

不会立刻刷新。

而是:


Dirty = true

加入:


Dirty Queue

例如:

连续:


count++
count++
count++
count++

不会刷新四次。

而是:


Dirty

↓

下一帧

↓

统一刷新

类似:

React Batched Update。


第十三章 为什么不能在 build 修改 State?

错误:


build(){

this.count++

Text()
}

因为:


build()

↓

修改State

↓

重新build()

↓

再次修改State

↓

死循环

因此官方禁止:


Build里面改State

第十四章 @State 与 @Prop、@Link、@Observed、@ObjectLink 的关系

装饰器 作用 数据流
@State 当前组件私有状态 组件内部
@Prop 父组件传值 单向
@Link 父子双向绑定 双向
@Observed 让对象属性具备响应式 对象级
@ObjectLink 监听 @Observed 对象 引用对象

可以理解为:

  • @State:管理组件自己的状态。
  • @Prop:父组件向子组件传递只读数据。
  • @Link:父子共享同一份可修改的数据。
  • @Observed:让对象内部字段变化也能被观察。
  • @ObjectLink:子组件引用并监听 @Observed 对象。

第十五章 常见问题与最佳实践

1. @State 适合什么数据?

适合组件内部临时状态,例如:

  • 当前计数
  • 输入框内容
  • 开关状态
  • 当前 Tab
  • Loading 状态

2. 不适合什么数据?

不建议用于:

  • 全局共享状态
  • 跨页面共享数据
  • 大型业务对象
  • 长生命周期数据

这类数据更适合使用应用级状态管理方案。

3. 更新对象数据的建议

优先使用不可变更新:


this.user = {
  ...this.user,
  name: "Jack"
}

如果需要频繁修改对象内部字段,可考虑使用 @Observed 配合 @ObjectLink


总结

@State 是 HarmonyOS ArkUI 响应式系统中最基础、最核心的状态管理能力。它的价值并不只是“保存数据”,而是在数据变化时,将变化通知框架,由框架完成脏标记、调度刷新、重新执行 build(),并借助 Diff 算法,仅更新真正发生变化的 UI 节点。

理解 @State 的底层机制后,你会更容易掌握整个 ArkUI 状态管理体系,包括 @Prop@Link@Observed@ObjectLink 以及更高级的应用状态管理模式。

一句话概括:

@State = 响应式状态 + 变化通知 + UI 自动刷新,而不仅仅是一个普通变量。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐