eagleye

ArkTS V1 与 V2 装饰器映射关系企业级参考文档

ArkTS V1 与 V2 装饰器映射关系企业级参考文档

本文档基于 HarmonyOS NEXT API 12+ 标准,详细梳理了 @Component(V1)与 @ComponentV2(V2)两套组件体系下的装饰器映射关系、使用差异、代码示例及迁移注意事项,为项目从V1向V2迁移提供权威参考手册。

 

文档说明

本文档中的V1代指使用 @Component 装饰器的传统组件体系,V2代指使用 @ComponentV2 装饰器的新一代组件体系。所有映射关系均基于官方正式发布的API规范整理。

 

一、装饰器核心映射关系总览

V1 (@Component)

V2 (@ComponentV2)

功能说明

@State

@Local

组件内部私有状态,变化时触发UI更新

@Prop

@Param

父组件向子组件单向传递数据

@Link

@Param + @Event

父子组件双向数据同步(V2推荐使用事件回传实现)

@Provide / @Consume

@Provider() / @Consumer()

跨层级组件状态传递与共享

-

@Event

子组件向父组件发送事件通知(V2新增)

@Watch

@Monitor

监听状态变化并执行回调逻辑

@Computed

自动支持

派生状态计算,V2无需显式声明,自动缓存结果

@Observed / @ObjectLink

自动支持

嵌套对象响应式监听,V2无需显式装饰

@StorageLink / @StorageProp

@Storage

本地存储状态绑定,V2统一为@Storage装饰器

-

@Effect

副作用处理,自动跟踪依赖变化(V2新增)

-

@Memo

计算结果缓存,避免重复计算(V2新增)

二、装饰器详细对比与代码示例

1. 组件内部状态:@State → @Local

用于定义组件内部私有的响应式状态,状态变化时触发当前组件UI更新。

特性

V1 @State

V2 @Local

作用范围

组件内部

组件内部

初始化要求

必须初始化

必须初始化

更新粒度

组件级

节点级(更细粒度)

性能

一般

更优

 

// V1 实现
@Component
struct Counter {
  @State count: number = 0;

  build() {
    Column() {
      Text(`Count: ${this.count}`)
      Button("Increment")
        .onClick(() => {
          this.count += 1;
        })
    }
  }
}

// V2 实现
@ComponentV2
struct CounterV2 {
  @Local count: number = 0;

  build() {
    Column() {
      Text(`Count: ${this.count}`)
      Button("Increment")
        .onClick(() => {
          this.count += 1;
        })
    }
  }
}

2. 单向数据传递:@Prop → @Param

用于父组件向子组件单向传递数据,父组件数据变化时自动同步到子组件。

特性

V1 @Prop

V2 @Param

数据流向

→子单向

→子单向

默认值支持

支持

支持(更灵活)

可选参数

需要显式声明?

支持默认值自动可选

类型校验

编译期校验

编译期+运行时校验

 

// V1 实现
@Component
struct UserCard {
  @Prop name: string;
  @Prop age: number = 18; // 可选参数,默认值18

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

// 父组件调用
@Component
struct Parent {
  build() {
    UserCard({ name: "张三" })
  }
}

// V2 实现
@ComponentV2
struct UserCardV2 {
  @Param name: string;
  @Param age: number = 18; // 可选参数,默认值18

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

// 父组件调用
@ComponentV2
struct ParentV2 {
  build() {
    UserCardV2({ name: "张三" })
  }
}

3. 双向数据同步:@Link → @Param + @Event

V1中通过@Link实现双向绑定,V2中推荐使用单向数据流+事件回传的方式实现,更符合单向数据流设计理念,状态变更更可控。

 

// V1 @Link 实现
@Component
struct Counter {
  @Link count: number;

  build() {
    Button(`Count: ${this.count}`)
      .onClick(() => {
        this.count += 1; // 直接修改父组件状态
      })
  }
}

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

  build() {
    Column() {
      Text(`父组件Count: ${this.count}`)
      Counter({ count: $count }) // 双向绑定
    }
  }
}

// V2 @Param + @Event 实现
@ComponentV2
struct CounterV2 {
  @Param count: number;
  @Event onCountChange: (newCount: number) => void; // 事件回调

  build() {
    Button(`Count: ${this.count}`)
      .onClick(() => {
        this.onCountChange(this.count + 1); // 通过事件回传新值
      })
  }
}

@ComponentV2
struct ParentV2 {
  @Local count: number = 0;

  build() {
    Column() {
      Text(`父组件Count: ${this.count}`)
      CounterV2({
        count: this.count,
        onCountChange: (newCount) => {
          this.count = newCount; // 父组件统一修改状态
        }
      })
    }
  }
}

 

 

设计理念说明

V2 不再推荐使用双向绑定,而是倡导单向数据流模式,所有状态变更都由持有状态的组件统一处理,状态流向更清晰,更容易追踪和调试。

 

4. 跨层级状态共享:@Provide/@Consume → @Provider()/@Consumer()

用于跨多层级组件传递状态,避免逐层传递属性。

 

// V1 实现
@Component
struct Grandparent {
  @Provide theme: string = "light";

  build() {
    Parent()
  }
}

@Component
struct Parent {
  build() {
    Child()
  }
}

@Component
struct Child {
  @Consume theme: string;

  build() {
    Text(`当前主题: ${this.theme}`)
      .fontColor(this.theme === "light" ? Color.Black : Color.White)
  }
}

// V2 实现
@ComponentV2
struct GrandparentV2 {
  @Provider theme: string = "light";

  build() {
    ParentV2()
  }
}

@ComponentV2
struct ParentV2 {
  build() {
    ChildV2()
  }
}

@ComponentV2
struct ChildV2 {
  @Consumer theme: string;

  build() {
    Text(`当前主题: ${this.theme}`)
      .fontColor(this.theme === "light" ? Color.Black : Color.White)
  }
}

5. 状态变化监听:@Watch → @Monitor

用于监听状态变化,状态变更时执行指定回调逻辑。

 

// V1 实现
@Component
struct UserProfile {
  @State userId: number = 0;

  @Watch('userId')
  onUserIdChange(newVal: number, oldVal: number) {
    console.log(`用户ID${oldVal}变为${newVal},加载用户信息`);
    this.loadUserInfo(newVal);
  }

  loadUserInfo(userId: number) {
    // 加载用户信息逻辑
  }

  build() {
    // UI实现
  }
}

// V2 实现
@ComponentV2
struct UserProfileV2 {
  @Local userId: number = 0;

  @Monitor('userId')
  onUserIdChange(newVal: number, oldVal: number) {
    console.log(`用户ID${oldVal}变为${newVal},加载用户信息`);
    this.loadUserInfo(newVal);
  }

  loadUserInfo(userId: number) {
    // 加载用户信息逻辑
  }

  build() {
    // UI实现
  }
}

6. V2 新增特性:@Effect 副作用处理

V2 新增的 @Effect 装饰器用于处理副作用,自动跟踪依赖变化,无需手动指定监听的状态。

 

@ComponentV2
struct SearchPage {
  @Local keyword: string = "";
  @Local page: number = 1;

  // keywordpage变化时自动触发,自动跟踪依赖
  @Effect
  searchData() {
    if (this.keyword.length > 0) {
      console.log(`搜索关键词: ${this.keyword}, 页码: ${this.page}`);
      // 执行搜索逻辑
    }
  }

  build() {
    Column() {
      Input({ placeholder: "请输入搜索关键词" })
        .onChange((value) => {
          this.keyword = value;
        })
      
      Button("下一页")
        .onClick(() => {
          this.page += 1;
        })
    }
  }
}

三、迁移注意事项

 

强制注意事项

所有装饰器的替换必须在 @ComponentV2 装饰的组件中使用,@Component 组件不支持V2系列装饰器。

 

1. 兼容性说明

• V1和V2装饰器不能混用在同一个组件中,一个组件要么全部使用V1装饰器,要么全部使用V2装饰器

• V1组件和V2组件可以互相引用,通过标准的属性传递和事件回调通信,完全兼容

• V2装饰器仅支持在API 12及以上版本使用,低版本系统无法运行

2. 迁移优先级建议

1. 优先替换:@State → @Local、@Prop → @Param、@Watch → @Monitor,这三类装饰器替换成本最低,性能提升明显

2. 逐步替换:@Link → @Param + @Event,需要调整数据流向,建议按模块逐步替换

3. 按需使用:@Event、@Effect、@Memo等新增特性,可在新功能开发时逐步引入

3. 常见迁移陷阱

• 陷阱1:V2组件中使用@State装饰器,编译报错。必须替换为@Local。

• 陷阱2:直接修改@Param接收的属性值,V2中@Param是只读的,必须通过@Event回传修改。

• 陷阱3:@Monitor装饰的方法参数顺序错误,V2中参数顺序是(newVal, oldVal),与V1保持一致。

• 陷阱4:忘记移除@Observed装饰器,V2中嵌套对象自动支持响应式,无需额外装饰。

• 陷阱5:@Effect中修改状态导致死循环,避免在副作用中直接修改依赖的状态。

4. 向后兼容方案

如果需要同时兼容V1和V2组件,可以使用条件编译实现:

 

// 条件编译兼容方案
#if (API_VERSION >= 12)
@ComponentV2
#else
@Component
#endif
struct CompatComponent {
#if (API_VERSION >= 12)
  @Local count: number = 0;
#else
  @State count: number = 0;
#endif

  build() {
    Button(`Count: ${this.count}`)
      .onClick(() => {
        this.count += 1;
      })
  }
}

四、迁移检查清单

执行组件从V1向V2迁移时,请对照以下清单逐一检查:

1. ✅ 组件装饰器已从 @Component 替换为 @ComponentV2

2. ✅ 所有 @State 已替换为 @Local

3. ✅ 所有 @Prop 已替换为 @Param

4. ✅ 所有 @Watch 已替换为 @Monitor

5. ✅ 所有 @Provide 已替换为 @Provider

6. ✅ 所有 @Consume 已替换为 @Consumer

7. ✅ 所有 @Link 已重构为 @Param + @Event 模式

8. ✅ 移除了不必要的 @Observed 装饰器

9. ✅ 没有直接修改 @Param 接收的属性值

10. ✅ 验证了所有状态更新逻辑正常工作

11. ✅ 验证了组件生命周期方法正常触发

12. ✅ 进行了性能测试,确认性能提升符合预期

五、官方建议与最佳实践

• 新功能优先使用V2:所有新增业务模块优先使用 @ComponentV2 + V2装饰器开发,享受性能提升和新特性

• 增量迁移:存量项目按模块逐步迁移,无需一次性全量替换,降低迁移风险

• 遵循单向数据流:V2中推荐使用单向数据流模式,避免使用双向绑定,提升代码可维护性

• 充分利用新特性:合理使用 @Effect、@Memo 等新特性,简化代码逻辑,提升性能

• 团队规范统一:制定团队统一的V2开发规范,避免不同开发者使用不同的编码风格

 

长期规划建议

HarmonyOS官方已明确V2是未来的发展方向,V1将进入维护模式。建议所有长期迭代的项目制定迁移计划,在1-2年内完成核心业务模块的V2迁移,以获得更好的性能和特性支持。

 

文档版本:V1.0 | 适配版本:HarmonyOS NEXT API 12+ | 更新日期:2024年4月

posted on 2026-04-08 10:41  GoGrid  阅读(34)  评论(0)    收藏  举报

导航