ArkTS 进阶之道(27):状态管理装饰器全景边界——V1/V2 双轨根因 @Component vs @ComponentV2
ArkTS 进阶之道27状态管理装饰器全景边界——V1/V2 双轨根因 Component vs ComponentV2本文是「ArkTS 进阶之道」系列第 27 篇续「ArkUI 状态联动」深水区。上篇讲 LocalStorageLink/LocalStorageProp 页面级状态绑定边界双向绑定 vs 单向只读。本文讲状态管理装饰器全景边界V1/V2 双轨根因——Component V1 装饰器体系 vs ComponentV2 V2 装饰器体系。能力系列篇 27 讲过 V1/V2 怎么用本文讲为哈 V1/V2 双轨合法 Component V1 装饰器体系不兼容 V2——根因在双轨装饰器体系边界。一、开篇状态管理装饰器不是单轨是 V1/V2 双轨体系你写 React 时状态管理是「hooks 魔法」useState/useEffect/useMemo 钩子// React 状态管理hooks 魔法useState/useEffect/useMemo 钩子 function Comp() { const [count, setCount] useState(0) // useState 钩子 const [theme, setTheme] useState(#007DFF) // useState 钩子 useEffect(() { console.log(count 变, count) }, [count]) // useEffect 钩子 return button onClick{() setCount(count 1)}count{count}/button } // React 状态管理hooks 魔法useState/useEffect/useMemo 钩子单轨你写鸿蒙 ArkTS 时状态管理是V1/V2 双轨体系——Component V1 装饰器体系 ComponentV2 V2 装饰器体系// ✅ V1 路径Component V1 装饰器体系State/Prop/Link/Provide/Consume Component struct V1Comp { State count: number 0 // ✅ V1 State 本地状态 Provide(theme) theme: string #007DFF // ✅ V1 Provide 跨层级传递 build() { Button(V1 count${this.count}).onClick(() { this.count }) } } // ✅ V2 路径ComponentV2 V2 装饰器体系Param/Once/Event/Provider/Consumer ComponentV2 struct V2Comp { Param count: number 0 // ✅ V2 Param 本地状态替代 V1 State Provider(theme) theme: string #007DFF // ✅ V2 Provider 跨层级传递替代 V1 Provide build() { Button(V2 count${this.count}).onClick(() { this.count }) } } // 状态管理 V1/V2 双轨Component V1 体系 ComponentV2 V2 体系双轨装饰器体系hooks 魔法 vs 双轨装饰器体系的区别React 把状态管理当 hooks 魔法useState/useEffect/useMemo 钩子单轨ArkTS 把状态管理当「V1/V2 双轨装饰器体系」Component V1 体系 ComponentV2 V2 体系双轨。根因不是 hooks 魔法是双轨装饰器体系——V1/V2 双轨Component V1 装饰器体系 ComponentV2 V2 装饰器体系双轨。二、根因V1/V2 双轨装饰器体系的机制鸿蒙 ArkUI 的状态管理是V1/V2 双轨装饰器体系绑定——Component V1 装饰器体系不兼容 V2ComponentV2 V2 装饰器体系不兼容 V1来自三重绑定机制。机制 1V1 装饰器体系——Component 装的 struct 只能用 V1 装饰器V1 装饰器体系**Component 装的 struct 只能用 V1 装饰器**——State/Prop/Link/Provide/Consume/Watch/Observed/ObjectLink/AppStorage/LocalStorage 全是 V1// ✅ V1 装饰器体系Component 装的 struct 只能用 V1 装饰器 Component struct V1Comp { State count: number 0 // ✅ V1 State 本地状态 Prop title: string // ✅ V1 Prop 单向只读 Link synced: number // ✅ V1 Link 双向绑定 Provide(theme) theme: string #007DFF // ✅ V1 Provide 跨层级传递 Consume(appTheme) appTheme: string // ✅ V1 Consume 跨层级消费 Watch(onCountChange) State watched: number 0 // ✅ V1 Watch 副作用回调 ObjectLink item: ObservedItem // ✅ V1 ObjectLink 嵌套对象引用 build() { Column() { Button(V1 count${this.count}).onClick(() { this.count }) } } } // V1 装饰器体系Component 装的 struct 只能用 V1 装饰器State/Prop/Link/Provide/Consume/Watch/ObjectLinkV1 装饰器体系V1Component装的 struct 只能用 V1 装饰器——State/Prop/Link/Provide/Consume/Watch/Observed/ObjectLink/AppStorage/LocalStorage 全是 V1。根因不是混用是 V1 装饰器体系——Component 装的 struct 只能用 V1 装饰器V1 体系全套装饰器。机制 2V2 装饰器体系——ComponentV2 装的 struct 只能用 V2 装饰器V2 装饰器体系**ComponentV2 装的 struct 只能用 V2 装饰器**——Param/Once/Event/Provider/Consumer/Computed 全是 V2// ✅ V2 脚饰器体系ComponentV2 装的 struct 只能用 V2 脚饰器 ComponentV2 struct V2Comp { Param count: number 0 // ✅ V2 Param 本地状态替代 V1 State Param({ once }) title: string // ✅ V2 Once 只同步一次替代 V1 Prop Event onCountChange: (n: number) void () {} // ✅ V2 Event 事件回调替代 V1 Link Provider(theme) theme: string #007DFF // ✅ V2 Provider 跨层级传递替代 V1 Provide Consumer(appTheme) appTheme: string // ✅ V2 Consumer 跨层级消费替代 V1 Consume Computed get doubled(): number { return this.count * 2 } // ✅ V2 Computed 计算属性替代 V1 Watch build() { Column() { Button(V2 count${this.count}).onClick(() { this.count }) } } } // V2 脚饰器体系ComponentV2 装的 struct 只能用 V2 脚饰器Param/Once/Event/Provider/Consumer/ComputedV2 脚饰器体系V2ComponentV2装的 struct 只能用 V2 脚饰器——Param/Once/Event/Provider/Consumer/Computed 全是 V2。根因不是混用是 V2 脚饰器体系——ComponentV2 装的 struct 只能用 V2 脚饰器V2 体系全套脚饰器。机制 3V1 vs V2 装饰器映射边界——同名功能不同名V1 vs V2 脚饰器映射边界同名功能不同名——V1 State → V2 ParamV1 Prop → V2 OnceV1 Link → V2 EventV1 Provide → V2 ProviderV1 Consume → V2 ConsumerV1 Watch → V2 Computed// ✅ V1 vs V2 脚饰器映射边界同名功能不同名 // V1 State 本地状态 → V2 Param 本地状态 Component struct V1StateComp { State count: number 0; build() {} } ComponentV2 struct V2ParamComp { Param count: number 0; build() {} } // V1 Prop 单向只读 → V2 Once 只同步一次 Component struct V1PropComp { Prop title: string ; build() {} } ComponentV2 struct V2OnceComp { Param({ once }) title: string ; build() {} } // V1 Link 双向绑定 → V2 Event 事件回调 Component struct V1LinkComp { Link synced: number; build() {} } ComponentV2 struct V2EventComp { Event onSync: (n: number) void () {}; build() {} } // V1 Provide 跨层级传递 → V2 Provider 跨层级传递 Component struct V1ProvideComp { Provide(theme) theme: string #007DFF; build() {} } ComponentV2 struct V2ProviderComp { Provider(theme) theme: string #007DFF; build() {} } // V1 Watch 副作用回调 → V2 Computed 计算属性 Component struct V1WatchComp { Watch(onCount) State count: number 0; build() {} } ComponentV2 struct V2ComputedComp { Param count: number 0; Computed get doubled(): number { return this.count * 2 }; build() {} } // V1 vs V2 脚饰器映射边界同名功能不同名State→Param, Prop→Once, Link→Event, Provide→Provider, Consume→Consumer, Watch→ComputedV1 vs V2 脚饰器映射边界V1 vs V2 脚饰器映射——同名功能不同名V1 State → V2 ParamV1 Prop → V2 OnceV1 Link → V2 EventV1 Provide → V2 ProviderV1 Consume → V2 ConsumerV1 Watch → V2 Computed。根因不是同名是同名功能不同名——V1 vs V2 装饰器映射同名功能不同名。机制 4V1/V2 不兼容边界——Component 不能用 V2 脚饰器ComponentV2 不能用 V1 脚饰器V1/V2 不兼容边界**Component 不能用 V2 装饰器ComponentV2 不能用 V1 脚饰器**——编译报错// ❌ Component 不能用 V2 脚饰器编译报错 Component struct BadV1Comp { Param count: number 0 // ❌ 编译报错Component 只能用 V1 脚饰器Param 是 V2 build() {} } // ❌ ComponentV2 不能用 V1 脚饰器编译报错 ComponentV2 struct BadV2Comp { State count: number 0 // ❌ 编译报错ComponentV2 只能用 V2 脚饰器State 是 V1 build() {} } // V1/V2 不兼容边界Component 不能用 V2 装饰器ComponentV2 不能用 V1 装饰器编译报错V1/V2 不兼容边界V1/V2 不兼容——Component 不能用 V2 装饰器Param 编译报错ComponentV2 不能用 V1 脚饰器State 编译报错。根因不是混用是 V1/V2 不兼容边界——Component 只能用 V1 装饰器ComponentV2 只能用 V2 脚饰器混用编译报错。三、真机配图状态管理装饰器全景边界——V1 路径全套装饰器同步初始态V1 装饰器体系全套 State localCount0、Provide theme“#007DFF” 葝色、ObjectLink item.count0 均 V1 路径初始态齐点调三按钮后State localCount1、Provide theme“#FF4D4F” 红色文字、ObjectLink item.count1 均 V1 路径全套装饰器同步证据齐对比证据点改 State localCount 后 localCount1 刷 UIV1 State 本地状态赋值刷 UI点改 Provide theme红色后 theme“#FF4D4F” 红色文字同步V1 Provide 跨层级传递祖辈定义后辈消费点改 ObjectLink item.count 后 item.count1 刷 UIV1 ObjectLink 嵌套对象引用子属性改刷 UI。V1 装饰器体系全套同步——State/Provide/ObjectLink 均 V1 路径装饰器体系全套同步V2 路径对比表格讲根因ComponentV2 API 23 真机 API 21 跑不动。四、V1 vs V2 装饰器全景对照表V1 装饰器ComponentV2 装饰器ComponentV2功能边界StateParam本地状态赋值刷 UI 依赖追踪PropParam({ once }) / Once单向只读父改子同步子不改LinkEvent双向绑定父改子同步子改父同步ProvideProvider跨层级传递祖辈定义后辈消费ConsumeConsumer跨层级消费后辈消费祖辈状态WatchComputed副作用/计算属性变触发回调ObservedObservedV2 兼容标记类可观测嵌套对象子属性改触发ObjectLinkParamV2 接收 Observed嵌套对象引用子属性改刷子组件 UIAppStorage StorageLinkParamV2 不用 AppStorage应用级状态所有页面共享LocalStorage LocalStorageLinkParamV2 不用 LocalStorage页面级状态同页面多组件共享全景对照核心V1 用 AppStorage/LocalStorage 存储槽 StorageLink/LocalStorageLink 绑定V2 直接用 ParamV2 不用 AppStorage/LocalStorage 存储槽V2 状态都绑在 Param。V1 Watch 副作用回调 vs V2 Computed 计算属性V2 用 Computed 替代 Watch计算属性自动追踪依赖。V1 Link 双向绑定 vs V2 Event 事件回调V2 用 Event 替代 Link子改父用事件回调不双向绑定。五、真解法V1/V2 双轨选用的三个场景场景 1V1 路径首选90% 场景首选Component V1 装饰器体系// ✅ V1 路径Component V1 装饰器体系首选90% 场景 Component struct V1Comp { State count: number 0 // ✅ V1 State 本地状态 Provide(theme) theme: string #007DFF // ✅ V1 Provide 跨层级传递 ObjectLink item: ObservedItem // ✅ V1 ObjectLink 嵌套对象引用 build() { Column() { Text(V1 count${this.count}).fontColor(this.theme) Button(改 count).onClick(() { this.count }) } } } // V1 路径首选Component V1 装饰器体系State/Prop/Link/Provide/Consume/Watch/ObjectLink 全套为哈能跑V1 路径首选——Component V1 装饰器体系全套State/Prop/Link/Provide/Consume/Watch/Observed/ObjectLink/AppStorage/LocalStorageAPI 21 全兼容90% 场景用 V1 就够。首选这个90% 的场景用 V1 装饰器体系就够。要写「状态管理本地/跨层级/嵌套/应用级/页面级等」时用这个——V1 装饰器体系全套兼容避坑 V2 API 23 限制。场景 2V2 路径新项目API 23 新项目用ComponentV2 V2 装饰器体系// ✅ V2 路径ComponentV2 V2 脚饰器体系API 23 新项目用 ComponentV2 struct V2Comp { Param count: number 0 // ✅ V2 Param 本地状态替代 V1 State Provider(theme) theme: string #007DFF // ✅ V2 Provider 跨层级传递替代 V1 Provide Computed get doubled(): number { return this.count * 2 } // ✅ V2 Computed 计算属性替代 V1 Watch build() { Column() { Text(V2 count${this.count} doubled${this.doubled}).fontColor(this.theme) Button(改 count).onClick(() { this.count }) } } } // V2 路径新项目ComponentV2 V2 装饰器体系Param/Once/Event/Provider/Consumer/Computed 全套为哈能跑V2 路径新项目——ComponentV2 V2 装饰器体系全套Param/Once/Event/Provider/Consumer/ComputedAPI 23 才兼容新项目用 V2。要写「状态管理新项目API 23 等」时用这个——V2 装饰器体系全套新项目用 V2Computed 计算属性替代 Watch 副作用回调更声明式Event 事件回调替代 Link 双向绑定更单向数据流。场景 3V1/V2 不混用边界同一 struct 只用一套混用编译报错// ❌ V1/V2 混用编译报错同一 struct 只用一套装饰器 Component struct BadMixV1Comp { State count: number 0 // ✅ V1 State Param title: string // ❌ 编译报错Component 只能用 V1Param 是 V2 build() {} } ComponentV2 struct BadMixV2Comp { Param count: number 0 // ✅ V2 Param State title: string // ❌ 编译报错ComponentV2 只能用 V2State 是 V1 build() {} } // ✅ V1/V2 不混用边界同一 struct 只用一套装饰器Component 用 V1ComponentV2 用 V2 Component struct PureV1Comp { State count: number 0; Prop title: string ; build() {} } ComponentV2 struct PureV2Comp { Param count: number 0; Param({ once }) title: string ; build() {} } // V1/V2 不混用边界同一 struct 只用一套装饰器混用编译报错Component 用 V1 或 ComponentV2 用 V2为哈能跑V1/V2 不混用边界——同一 struct 只用一套装饰器Component 用 V1ComponentV2 用 V2混用编译报错。要写「V1/V2 不混用同一 struct 只用一套等」时用这个——同一 struct 只用一套装饰器Component 用 V1 或 ComponentV2 用 V2混用编译报错。六、一句话哲学状态管理装饰器不是单轨是 V1/V2 双轨装饰器体系的同名功能不同名。ArkUI 的状态管理是 V1/V2 双轨装饰器体系——Component V1 装饰器体系State/Prop/Link/Provide/Consume/Watch/Observed/ObjectLink/AppStorage/LocalStorage ComponentV2 V2 装饰器体系Param/Once/Event/Provider/Consumer/Computed。根因不是单轨是双轨装饰器体系——V1 装饰器体系Component 装的 struct 只能用 V1 装饰器 V2 装饰器体系ComponentV2 装的 struct 只能用 V2 装饰器 V1 vs V2 装饰器映射边界同名功能不同名State→Param, Prop→Once, Link→Event, Provide→Provider, Consume→Consumer, Watch→Computed V1/V2 不兼容边界Component 不能用 V2 装饰器ComponentV2 不能用 V1 装饰器混用编译报错。对比 React 状态管理 hooks 魔法useState/useEffect/useMemo 钩子单轨ArkTS 状态管理 V1/V2 双轨装饰器体系同名功能不同名。状态联动深水区串讲Watch 绑 State 变触发副作用回调槽篇 68 Link $ 语法双向绑定跨组件同步篇 69 Provide/Consume 跨层级传递槽祖辈后辈同步篇 70 Observed/ObjectLink 嵌套对象观测槽子属性改刷 UI篇 71 AppStorage 应用级状态存储槽所有页面共享篇 72 LocalStorage 页面级状态存储槽同页面多组件共享篇 73 StorageLink/StorageProp 应用级状态绑定边界双向 vs 只读篇 74 LocalStorageLink/LocalStorageProp 页面级状态绑定边界双向 vs 只读篇 75 状态管理装饰器全景边界 V1/V2 双轨篇 76Component V1 体系 vs ComponentV2 V2 体系同名功能不同名——续「ArkUI 状态联动」深水区讲状态联动深水区Watch 协作用回调槽边界 Link $ 语法双向绑定边界 Provide/Consume 跨层级传递槽边界 Observed/ObjectLink 嵌套对象观测槽边界 AppStorage 应用级状态存储槽边界 LocalStorage 页面级状态存储槽边界 StorageLink/StorageProp 应用级状态绑定边界 LocalStorageLink/LocalStorageProp 页面级状态绑定边界 状态管理装饰器全景边界 V1/V2 双轨。系列预告下篇篇 77讲 PersistentStorage 持久化状态边界跨启动状态根因续「ArkUI 状态联动」深水区。五阶段哲学体系类型哲学50-52→ 作用域哲学53-55→ 状态哲学56-59→ 渎染哲学60-62→ 组件设计63-67→ 状态联动深水区68讲清 ArkTS/ArkUI 进阶哲学。能力系列回链能力系列篇本文进阶点篇 27 V1/V2 装饰器用法状态管理装饰器全景边界根因V1/V2 双轨同名功能不同名篇 13 State 基础用法状态哲学State 赋值就刷 UI 依赖追踪篇 59 Watch 用法状态联动深水区Watch 副作用回调槽 vs onClick 直接调副作用边界V1/V2 装饰器全景对照速查┌─────────────┬──────────────────────┬─────────────────────────────────┐ │ V1Component│ V2ComponentV2 │ 功能边界 │ ├─────────────┼──────────────────────┼─────────────────────────────────┤ │ State │ Param │ 本地状态赋值刷 UI 依赖追踪 │ │ Prop │ Param({ once })/Once│ 单向只读父改子同步子不改 │ │ Link │ Event │ 双向绑定/事件回调父子同步 │ │ Provide │ Provider │ 跨层级传递祖辈定义后辈消费 │ │ Consume │ Consumer │ 跨层级消费后辈消费祖辈状态 │ │ Watch │ Computed │ 副作用/计算属性变触发回调 │ │ Observed │ ObservedV2 兼容 │ 标记类可观测嵌套对象子属性改 │ │ ObjectLink │ ParamV2 接收 │ 嵌套对象引用子属性改刷子组件 │ │ AppStorage │ ParamV2 不用 │ 应用级状态所有页面共享 │ │ LocalStorage │ ParamV2 不用 │ 页面级状态同页面多组件共享 │ └─────────────┴──────────────────────┴─────────────────────────────────┘写鸿蒙 ArkUI 记住状态管理装饰器不是单轨是 V1/V2 双轨装饰器体系的同名功能不同名——V1 脚饰器体系Component 装的 struct 只能用 V1 装饰器State/Prop/Link/Provide/Consume/Watch/Observed/ObjectLink/AppStorage/LocalStorage V2 装饰器体系ComponentV2 装的 struct 只能用 V2 装饰器Param/Once/Event/Provider/Consumer/Computed V1 vs V2 脚饰器映射边界同名功能不同名State→Param, Prop→Once, Link→Event, Provide→Provider, Consume→Consumer, Watch→Computed V1/V2 不兼容边界Component 不能用 V2 装饰器ComponentV2 不能用 V1 装饰器混用编译报错。V1 路径首选用 Component V1 装饰器体系全套90% 场景API 21 全兼容V2 路径新项目用 ComponentV2 V2 装饰器体系全套API 23 新项目Computed 计算属性替代 Watch 副作用回调更声明式Event 事件回调替代 Link 双向绑定更单向数据流V1/V2 不混用边界同一 struct 只用一套装饰器混用编译报错。V1/V2 双轨同名功能不同名是 ArkUI 状态联动深水区核心