ArkUI V2 是 HarmonyOS 5.0 引入的新一代 UI 框架本篇将深入讲解 ImportantDays 项目中使用到的 V2 装饰器包括 ComponentV2、ObservedV2、Trace、Param、Local、Monitor 等。一、ArkUI V1 vs V2 对比1.1 为什么需要 V2ArkUI V1 使用Component、State、Prop、Link、Observed、ObjectLink等装饰器。虽然功能完善但存在一些痛点嵌套传递复杂Prop和Link需要逐层传递深层组件通信繁琐对象观察粒度粗Observed只能观察整个对象无法精确到属性级别代码冗余需要大量样板代码来实现响应式ArkUI V2 引入了更优雅的解决方案特性V1V2组件声明ComponentComponentV2状态管理State/Prop/LinkLocal/Param对象观察ObservedObjectLinkObservedV2Trace变化监听WatchMonitor全局存储AppStorageAppStorageV21.2 本项目使用的 V2 特性ImportantDays 项目全面采用 ArkUI V2以下是在各文件中的使用情况ObservedV2 → ImportantDay, AvoidArea, MainViewModel ComponentV2 → 所有组件和页面 Trace → ImportantDay 属性, AvoidArea 属性, MainViewModel 属性 Local → 页面和组件的本地状态 Param → 组件输入参数DayCard, CalendarGridView, ColorPicker Monitor → 数据变化监听ImportantDayListPage, DayCard, StatPanel, CalendarPage AppStorageV2 → 全局状态AvoidArea二、ObservedV2 与 Trace精确的对象观察2.1 基本用法在 V1 中要让一个类的属性可观察需要使用Observed装饰类然后在子组件中用ObjectLink接收。V2 的方式更加直接// model/ImportantDay.etsObservedV2exportclassImportantDay{Traceid:string;Tracetitle:string;Tracedate:string;Tracedescription:string;TracecolorIndex:number0;TracecountMode:numberCountMode.COUNTDOWN;TracerepeatType:numberRepeatType.NONE;TraceadvanceDays:number0;TraceisPinned:booleanfalse;TracecreatedAt:number0;TraceupdatedAt:number0;constructor(id:string,title:string,date:string){this.idid;this.titletitle;this.datedate;this.createdAtDate.now();this.updatedAtDate.now();}}2.2 Trace 的精确观察Trace装饰器的核心优势是属性级别的精确观察。当title变化时只有依赖title的 UI 会刷新不会触发整个对象的重新渲染。例如在DayCard组件中Monitor(day.date,day.countMode,day.repeatType)onDayChange():void{this.refreshData();}这里精确监听了day对象的date、countMode、repeatType三个属性。只有这三个属性变化时才触发刷新其他属性如description、colorIndex变化不会触发。2.3 嵌套对象的观察// model/AvoidArea.etsObservedV2exportclassAvoidArea{TracetopRectHeight:number0;TracebottomRectHeight:number0;constructor(topRectHeight:number,bottomRectHeight:number){this.topRectHeighttopRectHeight;this.bottomRectHeightbottomRectHeight;}}AvoidArea用于管理安全区域高度通过AppStorageV2全局共享所有页面都能响应安全区域变化。三、ComponentV2 与 Local组件与本地状态3.1 ComponentV2ComponentV2是 V2 版本的组件声明装饰器替代 V1 的ComponentComponentV2exportstruct DayCard{// 组件实现}3.2 Local本地状态Local替代 V1 的State声明组件内部管理的本地状态ComponentV2exportstruct StatPanel{privatevm:MainViewModelMainViewModel.instance;Localtotal:number0;Localupcoming:number0;Localpassed:number0;LocalthisMonth:number0;aboutToAppear():void{this.refreshStats();}}Local的特点只在当前组件内可读写变化时自动触发当前组件的 UI 刷新不需要像 V1 的State那样做特殊处理3.3 页面中的 Local在页面中Local用于管理页面级别的状态ComponentV2exportstruct ImportantDayListPage{privatevm:MainViewModelMainViewModel.instance;LocalavoidArea:AvoidAreaAppStorageV2.connect(AvoidArea,()newAvoidArea(0,0))!;LocalsortedDays:ImportantDay[][];aboutToAppear():void{this.refreshList();}}这里sortedDays是排序后的列表仅在当前页面使用用Local管理。四、Param组件输入参数Param替代 V1 的Prop和部分Link的功能用于接收父组件传递的数据4.1 简单类型参数// components/ColorPicker.etsComponentV2exportstruct DayColorPicker{ParamselectedIndex:number0;ParamonSelect:(index:number)void(){};// ...}4.2 对象类型参数// components/DayCard.etsComponentV2exportstruct DayCard{Paramday:ImportantDaynewImportantDay(,,);// ...}4.3 回调函数参数// components/CalendarGridView.etsComponentV2exportstruct CalendarGridView{ParammonthData:CalendarMonthData{year:0,month:0,cells:[]};ParamonSelectDate:(date:string)void(){};// ...}Param的特点数据从父组件单向流入子组件不能直接修改Param的值当父组件数据变化时子组件自动更新支持函数类型的参数V1 中较难实现五、Monitor变化监听Monitor替代 V1 的Watch功能更强大5.1 监听 ViewModel 数据变化// pages/ImportantDayListPage.etsMonitor(vm.dayList)onDayListChange():void{this.refreshList();}Monitor(vm.sortType)onSortChange():void{this.refreshList();}当MainViewModel的dayList或sortType发生变化时自动触发列表刷新。5.2 监听对象属性变化// components/DayCard.etsMonitor(day.date,day.countMode,day.repeatType)onDayChange():void{this.refreshData();}可以同时监听多个属性路径任一变化都会触发。5.3 监听全局状态// pages/CalendarPage.etsMonitor(vm.dayList)onDayListChange():void{this.dataSource.reloadData();this.selectedDayListthis.vm.getDaysForDate(this.selectedDate);}六、AppStorageV2全局状态管理AppStorageV2是 V2 版本的全局状态管理支持存储ObservedV2对象// 在 EntryAbility 中初始化AppStorageV2.connect(AvoidArea,()newAvoidArea(topRectHeight,bottomRectHeight));// 在任意页面中读取LocalavoidArea:AvoidAreaAppStorageV2.connect(AvoidArea,()newAvoidArea(0,0))!;当AvoidArea的Trace属性变化时所有连接的页面都会收到更新。七、Entry 与 ComponentV2 的配合标记为Entry的页面需要同时使用ComponentV2// pages/MainEntry.etsEntryComponentV2struct MainEntry{privatevm:MainViewModelMainViewModel.instance;LocalavoidArea:AvoidAreaAppStorageV2.connect(AvoidArea,()newAvoidArea(0,0))!;build(){// ...}}八、V2 开发注意事项8.1 不能混用 V1 和 V2 装饰器同一个struct中不能混用 V1 和 V2 装饰器。例如不能在ComponentV2中使用State。8.2 Param 的默认值Param必须提供默认值即使父组件一定会传递值Paramday:ImportantDaynewImportantDay(,,);// 必须有默认值8.3 Monitor 的路径格式Monitor使用字符串路径监听支持点号访问嵌套属性Monitor(day.date)// 监听 day 对象的 date 属性Monitor(vm.dayList)// 监听 vm 的 dayList 属性8.4 ObservedV2 需要配合 TraceObservedV2类中只有被Trace装饰的属性才是可观察的未被装饰的属性变化不会触发 UI 更新。九、小结ArkUI V2 带来了更优雅、更精确的响应式编程体验。ObservedV2Trace实现属性级观察Param简化父子通信Monitor提供灵活的变化监听。ImportantDays 项目全面采用 V2 特性代码更加简洁、可维护性更强。
HarmonyOs应用《重要日》开发第3篇 - @ComponentV2 响应式编程
发布时间:2026/7/16 5:05:55
ArkUI V2 是 HarmonyOS 5.0 引入的新一代 UI 框架本篇将深入讲解 ImportantDays 项目中使用到的 V2 装饰器包括 ComponentV2、ObservedV2、Trace、Param、Local、Monitor 等。一、ArkUI V1 vs V2 对比1.1 为什么需要 V2ArkUI V1 使用Component、State、Prop、Link、Observed、ObjectLink等装饰器。虽然功能完善但存在一些痛点嵌套传递复杂Prop和Link需要逐层传递深层组件通信繁琐对象观察粒度粗Observed只能观察整个对象无法精确到属性级别代码冗余需要大量样板代码来实现响应式ArkUI V2 引入了更优雅的解决方案特性V1V2组件声明ComponentComponentV2状态管理State/Prop/LinkLocal/Param对象观察ObservedObjectLinkObservedV2Trace变化监听WatchMonitor全局存储AppStorageAppStorageV21.2 本项目使用的 V2 特性ImportantDays 项目全面采用 ArkUI V2以下是在各文件中的使用情况ObservedV2 → ImportantDay, AvoidArea, MainViewModel ComponentV2 → 所有组件和页面 Trace → ImportantDay 属性, AvoidArea 属性, MainViewModel 属性 Local → 页面和组件的本地状态 Param → 组件输入参数DayCard, CalendarGridView, ColorPicker Monitor → 数据变化监听ImportantDayListPage, DayCard, StatPanel, CalendarPage AppStorageV2 → 全局状态AvoidArea二、ObservedV2 与 Trace精确的对象观察2.1 基本用法在 V1 中要让一个类的属性可观察需要使用Observed装饰类然后在子组件中用ObjectLink接收。V2 的方式更加直接// model/ImportantDay.etsObservedV2exportclassImportantDay{Traceid:string;Tracetitle:string;Tracedate:string;Tracedescription:string;TracecolorIndex:number0;TracecountMode:numberCountMode.COUNTDOWN;TracerepeatType:numberRepeatType.NONE;TraceadvanceDays:number0;TraceisPinned:booleanfalse;TracecreatedAt:number0;TraceupdatedAt:number0;constructor(id:string,title:string,date:string){this.idid;this.titletitle;this.datedate;this.createdAtDate.now();this.updatedAtDate.now();}}2.2 Trace 的精确观察Trace装饰器的核心优势是属性级别的精确观察。当title变化时只有依赖title的 UI 会刷新不会触发整个对象的重新渲染。例如在DayCard组件中Monitor(day.date,day.countMode,day.repeatType)onDayChange():void{this.refreshData();}这里精确监听了day对象的date、countMode、repeatType三个属性。只有这三个属性变化时才触发刷新其他属性如description、colorIndex变化不会触发。2.3 嵌套对象的观察// model/AvoidArea.etsObservedV2exportclassAvoidArea{TracetopRectHeight:number0;TracebottomRectHeight:number0;constructor(topRectHeight:number,bottomRectHeight:number){this.topRectHeighttopRectHeight;this.bottomRectHeightbottomRectHeight;}}AvoidArea用于管理安全区域高度通过AppStorageV2全局共享所有页面都能响应安全区域变化。三、ComponentV2 与 Local组件与本地状态3.1 ComponentV2ComponentV2是 V2 版本的组件声明装饰器替代 V1 的ComponentComponentV2exportstruct DayCard{// 组件实现}3.2 Local本地状态Local替代 V1 的State声明组件内部管理的本地状态ComponentV2exportstruct StatPanel{privatevm:MainViewModelMainViewModel.instance;Localtotal:number0;Localupcoming:number0;Localpassed:number0;LocalthisMonth:number0;aboutToAppear():void{this.refreshStats();}}Local的特点只在当前组件内可读写变化时自动触发当前组件的 UI 刷新不需要像 V1 的State那样做特殊处理3.3 页面中的 Local在页面中Local用于管理页面级别的状态ComponentV2exportstruct ImportantDayListPage{privatevm:MainViewModelMainViewModel.instance;LocalavoidArea:AvoidAreaAppStorageV2.connect(AvoidArea,()newAvoidArea(0,0))!;LocalsortedDays:ImportantDay[][];aboutToAppear():void{this.refreshList();}}这里sortedDays是排序后的列表仅在当前页面使用用Local管理。四、Param组件输入参数Param替代 V1 的Prop和部分Link的功能用于接收父组件传递的数据4.1 简单类型参数// components/ColorPicker.etsComponentV2exportstruct DayColorPicker{ParamselectedIndex:number0;ParamonSelect:(index:number)void(){};// ...}4.2 对象类型参数// components/DayCard.etsComponentV2exportstruct DayCard{Paramday:ImportantDaynewImportantDay(,,);// ...}4.3 回调函数参数// components/CalendarGridView.etsComponentV2exportstruct CalendarGridView{ParammonthData:CalendarMonthData{year:0,month:0,cells:[]};ParamonSelectDate:(date:string)void(){};// ...}Param的特点数据从父组件单向流入子组件不能直接修改Param的值当父组件数据变化时子组件自动更新支持函数类型的参数V1 中较难实现五、Monitor变化监听Monitor替代 V1 的Watch功能更强大5.1 监听 ViewModel 数据变化// pages/ImportantDayListPage.etsMonitor(vm.dayList)onDayListChange():void{this.refreshList();}Monitor(vm.sortType)onSortChange():void{this.refreshList();}当MainViewModel的dayList或sortType发生变化时自动触发列表刷新。5.2 监听对象属性变化// components/DayCard.etsMonitor(day.date,day.countMode,day.repeatType)onDayChange():void{this.refreshData();}可以同时监听多个属性路径任一变化都会触发。5.3 监听全局状态// pages/CalendarPage.etsMonitor(vm.dayList)onDayListChange():void{this.dataSource.reloadData();this.selectedDayListthis.vm.getDaysForDate(this.selectedDate);}六、AppStorageV2全局状态管理AppStorageV2是 V2 版本的全局状态管理支持存储ObservedV2对象// 在 EntryAbility 中初始化AppStorageV2.connect(AvoidArea,()newAvoidArea(topRectHeight,bottomRectHeight));// 在任意页面中读取LocalavoidArea:AvoidAreaAppStorageV2.connect(AvoidArea,()newAvoidArea(0,0))!;当AvoidArea的Trace属性变化时所有连接的页面都会收到更新。七、Entry 与 ComponentV2 的配合标记为Entry的页面需要同时使用ComponentV2// pages/MainEntry.etsEntryComponentV2struct MainEntry{privatevm:MainViewModelMainViewModel.instance;LocalavoidArea:AvoidAreaAppStorageV2.connect(AvoidArea,()newAvoidArea(0,0))!;build(){// ...}}八、V2 开发注意事项8.1 不能混用 V1 和 V2 装饰器同一个struct中不能混用 V1 和 V2 装饰器。例如不能在ComponentV2中使用State。8.2 Param 的默认值Param必须提供默认值即使父组件一定会传递值Paramday:ImportantDaynewImportantDay(,,);// 必须有默认值8.3 Monitor 的路径格式Monitor使用字符串路径监听支持点号访问嵌套属性Monitor(day.date)// 监听 day 对象的 date 属性Monitor(vm.dayList)// 监听 vm 的 dayList 属性8.4 ObservedV2 需要配合 TraceObservedV2类中只有被Trace装饰的属性才是可观察的未被装饰的属性变化不会触发 UI 更新。九、小结ArkUI V2 带来了更优雅、更精确的响应式编程体验。ObservedV2Trace实现属性级观察Param简化父子通信Monitor提供灵活的变化监听。ImportantDays 项目全面采用 V2 特性代码更加简洁、可维护性更强。