当前位置:首页>鸿蒙APP>鸿蒙状态管理全解(State、Prop、Link、Provide、Consume、全局状态管理)

鸿蒙状态管理全解(State、Prop、Link、Provide、Consume、全局状态管理)

  • 2026-08-04 20:21:09
鸿蒙状态管理全解(State、Prop、Link、Provide、Consume、全局状态管理)

一、前言

状态管理是 ArkTS 开发的核心底层基石。页面文字、按钮禁用、列表数据、弹窗显隐、主题切换、用户信息缓存,所有会变化的UI,全部依赖状态驱动更新。

很多开发者写代码全靠“硬刷新页面”,不懂状态原理,导致项目后期极度难维护:

  • 组件数据更新不刷新、刷新错乱、重复渲染;

  • 父子组件传值单向、双向分不清,频繁出现数据不同步;

  • 多层嵌套组件传值层层透传,代码冗余、维护爆炸;

  • 全局状态滥用,页面互相污染、数据错乱、页面复现异常;

  • 分不清哪种状态适合哪种场景,全部无脑用 @State,性能差、耦合重。

本篇一次性讲透鸿蒙六大状态体系,从基础用法、传值流向、底层刷新原理、场景选型、全局状态工程化封装全覆盖,读完彻底告别状态混乱。

二、鸿蒙所有状态装饰器总览

先搞懂全局选型,开发不再乱用注解。

装饰器

作用域

数据流

核心用途

@State

组件内部

私有可变

组件自己的私有变化状态(按钮、显隐、输入框)

@Prop

子组件

父→子 单向

父传子,子组件只读,单向数据同步

@Link

子组件

父⇋子 双向

父子双向绑定,子改父同步(弹窗、开关、输入框)

@Provide

祖辈组件

跨层下发

跨多层传值,无需逐层透传

@Consume

后代组件

跨层接收

接收Provide数据,支持跨层双向更新

@Watch

任意状态

监听回调

监听状态变化,执行回调业务逻辑

三、基础核心:@State 私有状态

@State 是最基础的状态,作用于当前组件内部,数据变更自动驱动当前组件UI刷新,属于组件私有数据。

3.1 基础用法

@Entry@Componentstruct StateDemo {  // 组件私有状态  @State count: number = 0  build() {    Column({ space: 20 }) {      Text(`当前计数:${this.count}`)        .fontSize(20)      Button("点击+1")        .onClick(() => {          // 修改状态,自动刷新UI          this.count++        })    }    .width('100%')    .height('100%')    .justifyContent(FlexAlign.Center)  }}

3.2 核心特点

  • 仅当前组件可用,外部无法直接修改;

  • 数据可变,赋值即刷新视图;

  • 页面销毁自动回收,无全局污染。

适用场景:输入框内容、按钮禁用、弹窗显隐、计数器、开关状态等组件私有变量。

四、父子单向传值:@Prop

@Prop 用于 父组件向子组件单向传值,子组件数据跟随父组件变化,但子组件不能修改父数据,属于单向数据流。

4.1 父子单向传值实战

// 子组件@Componentstruct ChildPropItem {  // 接收父组件传值,单向绑定  @Prop msg: string  build() {    Text(`子组件接收:${this.msg}`)      .fontSize(18)      .fontColor('#666')  }}// 父组件@Entry@Componentstruct PropDemo {  @State parentText: string = "默认父组件数据"  build() {    Column({ space: 30 }) {      Button("修改父组件数据")        .onClick(() => {          this.parentText = "父组件数据已更新"        })      ChildPropItem({ msg: this.parentText })    }    .width('100%')    .justifyContent(FlexAlign.Center)  }}

父数据变 → 子自动变;子修改数据无效,保证单向数据流稳定。

五、父子双向绑定:@Link

@Link 是双向绑定,子组件修改数据,父组件同步更新,完美适配弹窗、开关、输入框等需要双向同步的场景。

5.1 双向绑定实战

// 子组件@Componentstruct LinkChildInput {  // 双向绑定父组件状态  @Link inputValue: string  build() {    TextInput({ text: this.inputValue })      .width(300)      .height(50)      .onChange((val) => {        // 子组件修改,父组件同步变化        this.inputValue = val      })  }}// 父组件@Entry@Componentstruct LinkDemo {  @State text: string = ""  build() {    Column({ space: 20 }) {      Text(`父组件实时内容:${this.text}`)      LinkChildInput({ inputValue: this.text })    }    .justifyContent(FlexAlign.Center)    .width('100%')  }}

核心区别:Prop 单向只读,Link 双向互通。

六、跨多层组件传值:Provide / Consume

当组件嵌套层级很深(父→子→孙→曾孙),使用 Prop/Link 需要逐层传参,代码极其冗余。

@Provide + @Consume 实现跨层级穿透传值,祖辈直接给后代传值,无需层层透传。

6.1 跨层状态更新实战

// 最底层子组件@Componentstruct GrandChild {  // 接收顶层Provide状态  @Consume themeColor: string  build() {    Text("深层子组件文本")      .fontSize(20)      .fontColor(this.themeColor)  }}// 中层组件@Componentstruct Child {  build() {    GrandChild()  }}// 顶层父组件@Entry@Componentstruct ProvideDemo {  // 全局提供状态,所有后代可直接消费  @Provide themeColor: string = "#007DFF"  build() {    Column({ space: 20 }) {      Button("切换颜色")        .onClick(() => {          this.themeColor = "#22c55e"        })      Child()    }  }}

顶层状态修改,深层组件自动刷新,彻底解决props逐层透传地狱。

七、状态监听:@Watch 监听状态变化

业务中经常需要:数据变化后自动请求接口、刷新列表、弹窗提示。@Watch 可以监听任意状态变更,触发回调函数。

@Entry@Componentstruct WatchDemo {  @State @Watch("onCountChange") count: number = 0  // 状态变化回调  onCountChange(newVal: number, oldVal: number) {    console.log(`旧值:${oldVal},新值:${newVal}`)    // 可执行接口请求、业务逻辑  }  build() {    Column() {      Text(`计数:${this.count}`)      Button("增加")        .onClick(() => this.count++)    }  }}

八、全局状态管理(商用项目必备)

页面之间共享数据(用户信息、登录状态、主题、全局配置),不能用页面级状态,需要全局单例状态。

8.1 全局状态仓库封装

// store/GlobalStore.etsexport default class GlobalStore {  // 单例  private static instance: GlobalStore  public static getInstance(): GlobalStore {    if (!this.instance) {      this.instance = new GlobalStore()    }    return this.instance  }  // 全局用户状态  userName: string = "未登录"  isLogin: boolean = false  // 修改全局状态方法  setUserInfo(name: string, login: boolean) {    this.userName = name    this.isLogin = login  }}

8.2 页面使用全局状态

import GlobalStore from '../store/GlobalStore'@Entry@Componentstruct GlobalStatePage {  // 全局实例  store = GlobalStore.getInstance()  build() {    Column({ space: 20 }) {      Text(`登录状态:${this.store.isLogin ? "已登录" : "未登录"}`)      Text(`用户名:${this.store.userName}`)      Button("模拟登录")        .onClick(() => {          this.store.setUserInfo("鸿蒙开发者", true)        })    }    .width('100%')    .justifyContent(FlexAlign.Center)  }}

九、状态开发高频坑点

  • @Prop 试图修改父数据:单向数据流,子修改不会同步父,导致数据不同步Bug;
  • 多层嵌套滥用Link:层级过深代码混乱,优先使用 Provide/Consume;
  • 全局状态随意修改:无封装方法,页面直接篡改属性,难以溯源;
  • 复杂对象直接赋值:状态无法监听,UI不刷新,需要解构或整体替换;
  • 忘记Watch新旧参数:无法比对数据变化,重复执行业务逻辑。
    十、全文总结
    鸿蒙状态管理有明确的层级分工:组件内部变化用@State、父子单向传值用 @Prop、双向同步用 @Link、跨层传值用 Provide/Consume、状态监听用 @Watch、页面共享用全局Store。
    商用项目想要代码整洁、数据稳定、渲染高性能,必须严格遵守数据流规范,杜绝乱用状态、暴力刷新页面,这是进阶鸿蒙开发工程师的必备能力。

最新文章

随机文章