🚩 一、什么是 @State
装饰器?
@Component
struct Counter {
@State count: number = 0;
build() {
Column() {
Text(`Count: ${this.count}`)
Button("Increment", () => this.count++);
}
}
}
✅ 作用:@State
是用于声明组件内部状态的装饰器。被标记的属性具有响应性,当它的值发生变化时,ArkUI 框架会自动重新构建依赖该状态的 UI 视图。
📌 特点:
- 只能用于组件(struct)内部;
- 被封装为“受控状态”;
- 在状态发生变化时触发组件 局部或整体重新渲染;
- 编译器完全接管 getter/setter 行为,开发者无需自己写更新逻辑。
⚙️ 二、ArkTS 编译器如何处理 @State
步骤一:装饰器识别阶段
编译器在构建 AST 时,识别 @State
装饰器,并记录以下内容:
- 属性名称(如
count
); - 初始值(
= 0
); - 所属组件(如
Counter
); - 属性在 UI 中被访问的方式(如绑定到
Text
文本中); - 属性是否被其他组件引用(比如是否通过
@Link
暴露)。
步骤二:状态代理代码注入
编译器不保留原始字段 count: number = 0
,而是将其转换为:
// 编译器生成后的伪代码逻辑
private __state_count: number = 0;
get count(): number {
return this.__state_count;
}
set count(value: number) {
if (this.__state_count !== value) {
this.__state_count = value;
this.markDirty(); // 通知 UI 更新
}
}
✔️ 特点:
- 使用私有变量存储真实值;
- 通过 getter / setter 访问;
- setter 会对比旧值,避免重复渲染;
markDirty()
是编译器生成的触发函数,告诉 ArkUI “状态发生了变化”。
步骤三:状态订阅绑定构建
在 build()
方法内使用 this.count
时,编译器还会:
- 插入依赖追踪代码(即让
Text(...)
依赖count
); - 将
Text
绑定到count
的 getter; - 自动注册该 UI 节点与该状态的绑定关系。
步骤四:生成字节码(Ark Bytecode)
最终 ArkCompiler 会把这些逻辑翻译成 Ark Bytecode。这个字节码包括:
功能块 | 对应生成的指令或伪逻辑 |
---|---|
初始化状态变量 | mov __state_count, 0 |
定义 getter | function count() { return __state_count } |
定义 setter | function count(val) { __state_count = val; notifyUpdate(); } |
UI 构建逻辑 | Text(count()) 等调用 |
状态变更追踪 | 注册 count 与 TextNode_1 的绑定关系 |
✅ 注意:Ark Bytecode 是运行于方舟虚拟机的中间语言,支持即时编译(JIT)和静态编译(AOT),不会保留 TypeScript 的运行时代码逻辑,性能远优于 JS。
🔁 三、运行时状态更新如何驱动 UI
当你执行 this.count++
时,ArkUI 渲染系统会按如下逻辑运行:
状态改变流程图:
this.count++
↓
setter 捕捉变化 → this.__state_count = 新值
↓
this.markDirty() → 标记组件为“需要更新”
↓
UI 渲染调度器执行下一帧更新任务
↓
只更新依赖了 this.count 的 Text 节点(局部刷新)
🎯 效率关键点:
- 仅更新变化状态的关联节点(不全量刷新);
- getter/setter 通过静态生成,运行无额外开销;
- 编译器按需插入依赖绑定代码,最大程度优化性能。
✅ 四、再看一次完整“编译前后”对比
开发者写的代码(ArkTS):
@State count: number = 0;
Text(`${this.count}`);
Button("Add", () => this.count++);
编译器生成的伪逻辑(字节码前):
private __state_count = 0;
get count() {
return this.__state_count;
}
set count(value) {
if (this.__state_count !== value) {
this.__state_count = value;
this.markDirty(); // 通知 UI 更新
}
}
build() {
// Text 节点绑定 getter
this.trackDependency('count', TextNode_1);
Text(this.count);
// Button 绑定 setter
Button("Add", () => this.count = this.count + 1);
}
编译后生成(简化示意的 Bytecode 逻辑):
L0: LoadGlobal "__state_count"
L1: CallFunction "Text" with Arg [__state_count]
L2: LoadFunction "Button"
L3: CreateClosure(() => {
Let temp = Load "__state_count"
temp = temp + 1
Store "__state_count", temp
Call "markDirty"
})
📌 总结:@State
的核心价值与实现精髓
维度 | 说明 |
---|---|
开发体验 | 用一句 @State 定义状态,无需管理更新逻辑 |
编译器行为 | 将字段转化为受控状态,注入 getter/setter 与 UI 通知 |
渲染机制 | 状态驱动、依赖追踪、局部更新、高性能 |
和 ArkUI 协作 | ArkUI 渲染管线根据状态变更自动触发对应视图刷新 |