10  第9章 状态管理进阶

🔄 第9章 状态管理进阶

单组件 @State 够用了吗?当应用变得复杂,状态需要跨组件、跨页面共享。本章系统梳理 ArkTS 的状态管理全景,从 @Provide/@Consume 到 AppStorage,掌握不同场景的最优选择。

10.1 9.1 状态管理全景

装饰器 作用范围 数据流向 典型场景
@State 组件内部 单组件 按钮点击计数、输入框值
@Prop 父→子 单向 展示组件接收配置
@Link 父↔︎子 双向 子组件修改父数据
@Provide/@Consume 祖先↔︎后代 双向跨层 主题色、语言设置
@Observed/@ObjectLink 嵌套对象 深度监听 数组/对象属性变化
AppStorage 全应用 全局共享 用户登录信息、主题
PersistentStorage 全应用+持久化 跨启动 用户偏好设置

10.2 9.2 @Provide / @Consume —— 跨层级共享

无需一层一层传递 @Prop,祖先直接 @Provide,后代随时 @Consume

// 祖先组件(App级别)
@Entry
@Component
struct AppRoot {
  @Provide('theme') currentTheme: string = 'light';  // 提供数据

  build() {
    Column() {
      ThemeToggle()   // 切换主题的子组件
      ContentArea()  // 使用主题的深层子组件
    }
  }
}

// 中间层(不需要感知 theme)
@Component
struct ContentArea {
  build() {
    Column() {
      DeepChild()  // 深层子组件
    }
  }
}

// 深层子组件(直接消费)
@Component
struct DeepChild {
  @Consume('theme') currentTheme: string;  // 消费数据,无需逐层传递

  build() {
    Text("当前主题:" + this.currentTheme)
      .fontColor(this.currentTheme === 'dark' ? '#fff' : '#333')
      .backgroundColor(this.currentTheme === 'dark' ? '#1a1a1a' : '#fff')
  }
}

🎨 主题跨层传递演示

AppRoot(@Provide theme)
ContentArea(中间层,不感知 theme)
DeepChild(@Consume theme)
当前主题:light ☀️

10.4 9.4 AppStorage —— 全应用状态

// 初始化(通常在 EntryAbility.ts 中)
AppStorage.setOrCreate('userId', 0);
AppStorage.setOrCreate('isLogin', false);
AppStorage.setOrCreate('userName', '游客');

// 组件中绑定
@Entry
@Component
struct HomePage {
  // 双向绑定全局状态
  @StorageLink('isLogin') isLogin: boolean = false;
  @StorageLink('userName') userName: string = '游客';

  build() {
    Column() {
      if (this.isLogin) {
        Text(`欢迎回来,${this.userName}!`)
        Button("退出登录").onClick(() => {
          this.isLogin = false;
          this.userName = '游客';
        })
      } else {
        Button("登录").onClick(() => {
          this.isLogin = true;
          this.userName = '张三';
        })
      }
    }
  }
}

🌐 AppStorage 全局状态演示

📦 AppStorage
isLogin: false
userName: "游客"
theme: "light"
请先登录
操作日志...

10.5 9.5 PersistentStorage —— 持久化存储

// 持久化存储:应用重启后数据仍存在
PersistentStorage.persistProp('colorMode', ColorMode.LIGHT);
PersistentStorage.persistProp('fontSize', 16);
PersistentStorage.persistProp('language', 'zh-CN');

@Entry
@Component
struct SettingsPage {
  @StorageProp('fontSize') fontSize: number = 16;   // 只读
  @StorageLink('fontSize') fontSizeLink: number = 16; // 可写

  build() {
    Column({ space: 16 }) {
      Text("字体大小设置")
        .fontSize(this.fontSize)  // 应用当前字号

      Slider({ value: this.fontSizeLink, min: 12, max: 24 })
        .onChange((v) => { this.fontSizeLink = v; }) // 修改 → 自动持久化
    }
  }
}

10.6 9.6 状态选型指南

🤔 我该用哪种状态管理?

Q: 数据只在本组件内使用?
Q: 父组件传值给子组件,子组件只展示?
Q: 子组件需要修改父组件数据?
Q: 深层嵌套组件需要祖先数据?
Q: 全应用需要共享的状态(如登录信息)?
Q: 用户偏好设置,重启后也要保留?