HarmonyOS:@State 装饰器——组件内状态

来源华为开发者官网 - @State装饰器:组件内状态
本笔记全面、系统地整理了该页面所有内容,包含详细说明、表格归纳、代码示例与核心知识点解析,便于深入学习和复习使用。

一、概述

    @State 是 ArkTS 中用于声明 组件内部状态变量 的装饰器。被 @State 修饰的变量具有响应式特性:当其值发生变化时,会自动触发 UI 重新渲染,从而实现动态交互效果。

  • 属于 本地状态管理

  • 仅可在自定义组件中使用

  • 支持基本类型和引用类型

  • 需要初始化赋值

  • 修改后自动驱动 UI 更新

二、核心特性概览表

特性说明
装饰器名称@State
作用目标自定义组件内的成员变量
是否必需初始化是,必须在声明时赋予初始值
支持的数据类型基本类型(numberstringboolean)、对象、数组等
响应式机制变量重新赋值可触发 UI 刷新;不支持对对象/数组内部的原地修改监听
作用域组件内部私有状态,不可跨组件共享
生命周期与组件实例绑定,随组件创建而初始化,销毁而释放
更新条件必须通过赋值操作符(=)改变整个变量的值才能触发 UI 更新
与其他装饰器关系可与 @Prop@Link@Provide@Consume 配合使用,但用途不同

三、语法格式

@State <variableName>: <Type> = <initialValue>;

示例:

@State count: number = 0;
@State title: string = "默认标题";
@State isActive: boolean = true;
@State userInfo: object = { name: "Tom", age: 18 };
@State list: Array<string> = ["A", "B", "C"];

四、完整代码示例

示例 1:基础计数器(数字类型)

@Component
struct CounterExample {
  @State count: number = 0;

  build() {
    Column({ space: 20 }) {
      Text(`当前计数:${this.count}`)
        .fontSize(24)
        .fontWeight(FontWeight.Bold)

      Button("增加")
        .onClick(() => {
          this.count += 1; // 触发 UI 更新
        })

      Button("减少")
        .onClick(() => {
          this.count -= 1; // 触发 UI 更新
        })
    }
    .width('100%')
    .padding(20)
  }
}

示例 2:布尔值控制显示隐藏

@Component
struct VisibilityExample {
  @State isVisible: boolean = true;

  build() {
    Column({ space: 20 }) {
      if (this.isVisible) {
        Text("这段文字可以被切换显示")
          .fontSize(20)
          .backgroundColor(Color.Blue)
          .padding(10)
          .textColor(Color.White)
      }

      Button(this.isVisible ? "隐藏" : "显示")
        .onClick(() => {
          this.isVisible = !this.isVisible; // 切换状态并刷新 UI
        })
    }
    .width('100%')
    .padding(20)
  }
}

示例 3:对象更新(需替换整个对象)

⚠️ 注意:直接修改属性不会触发 UI 更新!

@Component
struct ObjectUpdateExample {
  @State person: { name: string; age: number } = { name: "Alice", age: 30 };

  build() {
    Column({ space: 20 }) {
      Text(`姓名:${this.person.name}`)
        .fontSize(20)
      Text(`年龄:${this.person.age}`)
        .fontSize(20)

      Button("修改姓名")
        .onClick(() => {
          // ❌ 错误方式:不会触发 UI 更新
          // this.person.name = "Bob";

          // ✅ 正确方式:深拷贝或结构赋值后重新赋值
          this.person = { ...this.person, name: "Bob" };
        })

      Button("增加年龄")
        .onClick(() => {
          this.person = { ...this.person, age: this.person.age + 1 };
        })
    }
    .width('100%')
    .padding(20)
  }
}

示例 4:数组更新(不可变操作)

⚠️ 直接索引修改或 push 不会触发更新!

@Component
struct ArrayUpdateExample {
  @State items: string[] = ['Apple', 'Banana'];

  build() {
    Column({ space: 20 }) {
      ForEach(this.items, (item: string) => {
        Text(item)
          .fontSize(18)
          .padding(5)
          .borderRadius(4)
          .backgroundColor('#f0f0f0')
      }, item => item)

      Button("添加元素")
        .onClick(() => {
          // ✅ 使用 concat 返回新数组
          this.items = this.items.concat(`Item ${this.items.length + 1}`);
        })

      Button("删除第一个")
        .onClick(() => {
          // ✅ 使用 slice 创建新数组
          this.items = this.items.slice(1);
        })

      Button("使用 map 修改全部")
        .onClick(() => {
          this.items = this.items.map(item => `${item}-updated`);
        })
    }
    .width('100%')
    .padding(20)
  }
}

五、常见错误及正确做法对比表

操作类型错误写法是否触发 UI 更新正确写法是否触发 UI 更新
数字加减this.count++ 或 this.count += 1同上
字符串拼接this.msg += 'new'使用模板字符串再赋值
修改对象属性this.user.name = "New"this.user = { ...this.user, name: "New" }
修改数组元素this.list[0] = "X"this.list = [...this.list]; this.list[0]="X";
数组 pushthis.list.push("new")this.list = this.list.concat("new")
删除数组项this.list.splice(0,1)this.list = this.list.slice(1)

💡 小贴士:所有需要触发 UI 更新的操作都应遵循“不可变数据”原则 —— 返回一个新对象/新数组,并整体赋值给 @State 变量。

六、限制与注意事项

注意事项详细说明
不能用于静态变量@State static count: number = 0; ❌ 不允许
不能用于局部变量不能在函数内部使用 @State let x = 1; ❌
必须初始化@State count: number; ❌ 编译报错
不能为 undefined/null初始化值不能为 undefined 或 null(除非类型允许)
不监听深层变化对象嵌套层级过深时,需手动触发顶层对象替换
避免循环引用定义复杂对象时注意不要造成内存泄漏或无限递归

七、与其他状态装饰器对比表

装饰器数据流向使用场景是否响应式所属组件
@State内部状态管理组件自身状态当前组件
@Prop父→子(单向)接收父组件传递的只读属性✅(父变更触发子更新)子组件
@Link双向绑定子组件同步修改父组件状态子组件
@Provide / @Consume多层传递(祖先→后代)跨多级组件通信任意层级
@ObjectLink链接到 @State 对象在子组件中展示复杂对象✅(配合 @Observed子组件

八、最佳实践建议

实践推荐方式
命名规范使用有意义的名称,如 isLoadinguserNameitemList
单一职责每个 @State 变量尽量只负责一个逻辑状态
拆分复杂状态若对象过于复杂,考虑拆分为多个 @State 或结合 @Observed
使用不可变操作始终采用 mapfiltersliceconcat, 扩展运算符等方式生成新数据
性能优化避免频繁无意义的状态变更,防止过度重绘

九、总结

    @State 是构建动态 UI 的基石,它使得开发者可以通过简单的变量赋值来驱动界面更新。然而,必须理解其 响应式机制基于“赋值检测”而非“属性修改监听”,因此:

✅ 正确姿势是:永远用“新对象”或“新数组”替换旧值
❌ 错误姿势是:直接修改对象属性或数组元素而不重新赋值

掌握这一点是高效使用 ArkTS 进行 HarmonyOS 应用开发的关键前提。

知识点详解

  • 响应式系统原理:框架通过元数据拦截 @State 变量的 set 操作,触发 UI 重建。

  • 不可变数据模式:推荐使用函数式方法生成新数据,确保状态可追踪且可预测。

  • UI 自动刷新机制:每次 @State 变量被赋新值,都会调用组件的 build() 方法更新视图。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只小风华~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值