鸿蒙开发笔记

鸿蒙开发笔记-8-组件状态管理装饰器:@Provide/@Con

2025-03-07  本文已影响0人  今阳说

一、基本概念

1. @Provide与@Consume:跨组件树双向同步

这对装饰器实现了任意层级组件间的双向数据绑定。@Provide在祖先组件中声明共享状态,@Consume在后代组件中消费该状态,形成类似"发布-订阅"的机制。其突破传统父子传参的限制,支持组件树中任意层级的通信。

2. @Observed与@ObjectLink:深度数据观察

这对装饰器专为解决嵌套对象/数组的深度监听问题而设计。传统@State只能感知对象引用的变化,而@Observed通过代理机制实现对类属性的细粒度观察,@ObjectLink则建立与父组件@Observed实例的双向绑定。

二、使用方法

1. @Provide与@Consume

// 祖先组件提供共享主题配置
@Component
struct ThemeProvider {
  @Provide themeConfig = { 
    primaryColor: '#2196F3',
    fontSize: 16
  }
}

// 深层子组件消费配置
@Component
struct ButtonComponent {
  @Consume themeConfig: ThemeConfig
  
  build() {
    Button('提交')
      .backgroundColor(this.themeConfig.primaryColor)
      .fontSize(this.themeConfig.fontSize)
  }
}
@Component
struct Parent {
  @Provide({ allowOverride: true }) config = { theme: 'light' }
}

@Component
struct Child {
  @Provide config = { theme: 'dark' }  // 覆盖父级配置
}

2. @Observed与@ObjectLink

@Observed
class Product {
  constructor(public name: string, public stock: number) {}
}

// 父组件管理商品列表
@Component
struct ProductList {
  @State products: Product[] = [
    new Product('手机', 100),
    new Product('平板', 50)
  ]

  build() {
    Column() {
      ForEach(this.products, (item) => {
        ProductItem({ product: item })
      })
    }
  }
}

// 子组件修改库存
@Component
struct ProductItem {
  @ObjectLink product: Product

  build() {
    Row() {
      Text(`${this.product.name} 库存: ${this.product.stock}`)
      Button('-').onClick(() => this.product.stock--)
    }
  }
}

实现要点

三、应用场景

1. @Provide/@Consume适用场景

2. @Observed/@ObjectLink适用场景

四、进阶技巧

1. 联合类型与复杂结构

@Provide user: User | null = null  // 支持联合类型
@Consume('user') currentUser: User | null

@Observed
class Order {
  items: Map<number, CartItem> = new Map()  // 支持Map类型
}

优化策略

五、对比分析与选型指南

装饰器组合 核心功能 适用场景 优缺点对比
@State + @Link 父子组件单向/双向同步 简单父子状态传递 无法处理嵌套结构
@Provide + @Consume 跨层级组件双向同步 复杂组件树通信 需要严格命名规范
@Observed + @ObjectLink 嵌套对象/数组观察 二维数组、嵌套类属性监听 需要配合自定义类使用

关键差异

六、避坑指南

  1. 命名规范建议
    • 使用snake_case命名@Provide变量(如user_profile
    • 避免全局变量污染,优先使用别名隔离
  2. 性能优化:
    • 对大型数组/Map使用@Observed时,优先修改引用而非直接操作元素。
    • 使用readonly修饰不可变数据,减少不必要的代理开销。
  3. 常见错误处理
    • 未使用@Observed装饰类
    class User { ... }
    @ObjectLink user: User  // 运行时错误
    
    // 正确:
    @Observed class User { ... }
    
    • 确保@Consume变量在祖先组件中存在同名@Provide声明,避免运行时错误。

七、总结

我是今阳,如果想要进阶和了解更多的干货,欢迎关注wx gzh “今阳说” 接收我的最新文章

上一篇 下一篇

猜你喜欢

热点阅读