HarmonyOS 实战 | @State 不神秘——变量一变界面就跟着变

HarmonyOS 实战 | @State 不神秘——变量一变界面就跟着变
一、我们想解决什么问题打个比方先从生活里找感觉想象一下你家里有一个电灯。你想通过手机 App 来控制它的开关。最直接的做法是什么你按一下 App 上的按钮电灯亮了——这中间发生了什么其实是你的操作改变了一个状态灯是开还是关然后显示根据这个状态自动刷新了。这个逻辑在 HarmonyOS 里就是State要做的事。再举一个更贴近的例子你想做一个购物车页面购物车里有多少件商品这个数字会随着用户加减商品而变化。如果这个数字变了界面右上角的购物车图标旁边那个小红点就要跟着变。这个数字一变小红点就跟着变的需求就是State要解决的问题。传统写法的问题在最早的开发模式里假设我们写一个计数器页面数字从 0 开始每按一次按钮加 1。传统思路可能是这样声明一个变量count 0写一个按钮点击时count在界面上显示count听起来很简单对吧但问题来了——变量改了界面并不会自动更新。因为系统不知道这个变量和界面有什么关系它只会傻傻地渲染一次就完事了。这就好像你改了电视后面的电路但遥控器完全不知道你还是得手动走过去调。在 Android 原生开发的老办法里你得手动调用invalidate()或者写一堆观察者模式来通知界面更新。代码一长到处都是刷新界面的通知调用维护起来头疼得很。State 的解决思路HarmonyOS 的 ArkUI 框架引入了一套声明式 UI的理念核心思路就是我告诉系统哪些变量会变、它们一变界面就要跟着变。具体怎么告诉系统用State装饰器标记这些变量。先解释一下装饰器这个词。很多新手第一次看到State前面那个符号会觉得奇怪这是 TypeScript/ArkTS 里的语法叫装饰器Decorator。你可以把它理解为一个标记——用State标记一个变量就是告诉编译器这个变量不是普通的变量它是响应式的需要特殊对待。编译器看到State就会自动为它生成一套响应式逻辑你完全不需要自己写这部分代码。这套自动生成的机制是 ArkUI 框架在编译阶段悄悄帮你做的就像编译器自动给你的代码加了一行又一行的后台逻辑你看不到但它确实存在并且正常工作。这种约定大于配置的思路是现代框架的主流做法——你只要遵守约定就能享受框架带来的便利。先解释一下装饰器这个词。很多新手第一次看到State前面那个符号会觉得奇怪这是 TypeScript/ArkTS 里的语法叫装饰器Decorator。你可以把它理解为一个标记——用State标记一个变量就是告诉编译器这个变量不是普通的变量它是响应式的需要特殊对待。编译器看到State就会自动为它生成一套响应式逻辑你完全不需要自己写这部分代码。这套自动生成的机制是 ArkUI 框架在编译阶段悄悄帮你做的就像编译器自动给你的代码加了一行又一行的后台逻辑你看不到但它确实存在并且正常工作。这种约定大于配置的思路是现代框架的主流做法——你只要遵守约定就能享受框架带来的便利。先解释一下装饰器这个词。很多新手第一次看到State前面那个符号会觉得奇怪这是 TypeScript/ArkTS 里的语法叫装饰器Decorator。你可以把它理解为一个标记——用State标记一个变量就是告诉编译器这个变量不是普通的变量它是响应式的需要特殊对待。编译器看到State就会自动为它生成一套响应式逻辑你完全不需要自己写这部分代码。这套自动生成的机制是 ArkUI 框架在编译阶段悄悄帮你做的就像编译器自动给你的代码加了一行又一行的后台逻辑你看不到但它确实存在并且正常工作。这种约定大于配置的思路是现代框架的主流做法——你只要遵守约定就能享受框架带来的便利。打个比方State就像给变量装了一个小广播。一旦变量被改动了它就会大声喊变了变了界面快刷新然后系统收到信号就会自动更新 UI。整个过程不需要你手动调用什么刷新方法一切都是自动的。这就是响应式——变量响应变化界面响应变量。再用一个生活里的例子来加深印象想象你在用一个股票行情 App股价从 100 变成了 102界面上那个数字就自动变色了不需要你下拉刷新不需要你退出重进。这种体验背后的逻辑就是响应式编程在支撑。声明式 UI 的思维方式这里有一个思维方式的转变需要特别说明一下。在传统的命令式编程里你写代码告诉电脑第一步做什么、第二步做什么、第三步做什么。比如先找到文本框把里面的文字改成 “hello”再把背景色改成红色。这种写法非常具体但一旦界面复杂了你要写的步骤就爆炸了。而在声明式编程里你只描述结果长什么样。比如你告诉系统这个文本框的文字等于变量message文字颜色由isError决定——如果isError是 true 就红色否则黑色。至于怎么去改、什么时候改、怎么高效地改这些全交给框架处理。State就是这个声明的关键工具。你告诉框架count这个变量是响应式的它一变我的界面就要重新渲染。框架收到指令就会忠实地执行。这个思维方式的转变是理解 HarmonyOS 开发最重要的一步。很多人在学State的时候觉得别扭其实就是因为还在用命令式的思维去理解声明式的东西。换个角度一切就通了。二、数据模型设计用 interface 简洁定义数据结构我们先设计这个计数器案例要用到的数据结构。虽然这个案例很简单只有一个数字需要管理但养成好习惯很重要——用 TypeScript 的interface把数据结构定义清楚以后扩展也方便。// CounterData.ets// 定义计数器的数据结构exportinterfaceCounterData{count:number;// 当前计数值step:number;// 每次点击增减的步长}就这么简单。这个interface相当于一张卡片明确告诉我们一个计数器包含两个东西——当前的数字以及每次增减的步长。在实际项目里你可能有很多复杂的数据结构比如一个商品列表、用户信息表、购物车内容等等都可以先用interface定义清楚这样代码读起来一目了然。好处是类型检查会帮你把关字段写错了编辑器直接报错而不是等到运行时才发现问题。一个常见的数据结构扩展思路假设我们要做一个购物车购物车里有哪些东西呢可以这样设计exportinterfaceCartItem{id:string;// 商品IDname:string;// 商品名称price:number;// 单价quantity:number;// 购买数量}exportinterfaceCartData{items:CartItem[];// 购物车里的商品列表totalPrice:number;// 总价}然后在组件里Statecart:CartData{items:[],totalPrice:0};像这样先把数据模型定义清楚后面的业务逻辑写起来就顺了。虽然我们的计数器案例用不到这么复杂但这个思路要建立起来因为真实项目中数据结构往往是嵌套的。养成先定义数据结构再写业务逻辑的习惯好处非常明显第一接口文档即代码。你在interface里写的每个字段的名字、类型、注释就是最实时、最准确的文档。不需要额外维护一份文档代码一变文档自动过期这种事不会发生。第二编译期检查。TypeScript 的类型系统会在编译阶段就发现你拼错了字段名、用错了类型、传错了参数而不是等到用户操作到那一步才发现 bug。越早发现 bug修复成本越低。第三重构有底气。当你需要修改数据结构的时候interface定义了所有字段的形状改完 TS 编译器会告诉你哪些地方用了旧的字段名一键修复省心省力。所以强烈建议不管项目大小写State之前先写interface这个习惯会让你终身受益。三、核心设计决策方案对比不用 State vs 用 State我们先看一下为什么非要用State对比两种写法的区别维度不用 State普通变量用 State 装饰器界面是否自动刷新❌ 不刷新变量改界面不变✅ 自动刷新变量改界面跟着变需要手动刷新吗❌ 需要写额外代码通知系统✅ 不需要装饰器自动搞定可读性一般变量用途不明确高一看就知道这是响应式状态维护性差多了容易乱好状态集中管理适用场景组件内部不变的值需要驱动 UI 变化的值学习曲线无但用起来头疼有一点但用起来爽选型理由选State的原因很朴素省事、可读、易维护。省事是因为你不需要写任何手动刷新逻辑。传统开发里你要写一堆 observer、listener、callback声明式 UI 里一个State就全部搞定了。代码量直接少一个数量级维护起来自然也轻松。可读是因为State本身就是文档。别人看你的代码一眼就知道哪些变量是用来驱动界面的、哪些是纯计算的中间变量不需要猜。这是团队协作里特别有价值的事情——代码是给机器执行的但也是给人看的State让代码的自解释性大大增强。“易维护是因为逻辑集中。你改一个状态变量的值不需要到处找这个值改了之后应该刷新哪几个地方”框架自动帮你处理所有的关联刷新。如果将来需求变了需要在状态变化时多做一件事比如埋点上报你只需要在状态变更的地方处理就行不需要改一堆 UI 刷新的调用点。声明式 UI 的精髓就是你描述结果系统帮你实现过程。你不需要关心怎么刷新只需要告诉系统这个变量变了要刷新剩下的框架会帮你做。而且用State标记过的变量在代码里一眼就能看出来这个是用来驱动界面的状态团队协作的时候沟通成本也低。代码 review 的时候别人一看State就知道这部分是状态管理相关的逻辑不需要到处去找哪里改了值又改了 UI。什么时候不该用 State光知道什么时候用还不够知道什么时候不用同样重要。不需要用 State 的情况第一个纯计算的中间值。比如你有个变量doubleCount this.count * 2这只是count的两倍它不需要自己的State。因为只要count变了doubleCount自然跟着变它自己不需要是响应式的。第二个固定不变的配置常量。比如MAX_COUNT 100、API_BASE_URL https://api.example.com这种东西整个生命周期里都不会变加了State只是浪费。第三个从父组件传进来只需要读取的值。这种情况应该用Prop而不是State。State是给自己用的状态Prop是接收外部传入的值。四、完整代码实现全部代码就这一个文件我们的计数器案例写在一个.ets文件里就够了。代码不长我拆开来讲// Counter.etsimportpromptActionfromohos.promptAction;EntryComponentstruct CounterPage{Statecount:number0;// ① 标记为状态变量值从0开始Statestep:number1;// ② 步长也标记为状态build(){Column(){// 显示当前计数值Text(当前计数${this.count}).fontSize(40).fontWeight(FontWeight.Bold).margin({bottom:30})// 操作按钮区域Row({space:20}){Button(减少).onClick((){this.count-this.step;// ③ 点击后值变了})Button(增加).onClick((){this.countthis.step;// ④ 点击后值又变了})}// 重置按钮Button(重置).margin({top:20}).onClick((){this.count0;// ⑤ 重置为0promptAction.showToast({// ⑥ 顺便弹个提示message:已重置});})}.width(100%).height(100%).justifyContent(FlexAlign.Center)}}关键点逐行解读逐个解释一下上面带数字标注的地方①State count: number 0这是整个机制的核心。用State装饰器告诉系统count是一个响应式状态变量。它的初始值是0。一旦count的值发生变化UI 就会自动刷新。注意这个变量的位置——它是在Component装饰的struct内部、但在build()方法外部声明的。这是State变量必须待的地方。写在build()方法里面的局部变量哪怕加了State也没用因为局部变量超出函数作用域就销毁了。②State step: number 1步长也用State标记。这意味着如果我们加一个功能让用户可以调节步长比如从 1 变成 5界面也能及时响应。不过在这个简单例子里step暂时不变。③this.count - this.step点击减少按钮时修改this.count。注意这里有个细节this是必须的因为count是一个被State装饰器管理的类属性不是普通局部变量。通过this才能访问到类实例上的这个属性。如果你忘了写this直接写count - stepArkTS 会报编译错误因为count在这个作用域里找不到定义。④this.count this.step同理点击增加按钮时增加计数。由于count是State变量这行代码执行后框架检测到值变化会自动触发 UI 重新渲染屏幕上的数字就变成新的了。整个过程你不需要调用任何刷新方法不需要写this.update()或者this.forceUpdate()之类的框架全自动处理。⑤this.count 0重置逻辑。把计数归零UI 会同步刷新。⑥promptAction.showToast顺手加一个轻提示让用户知道重置成功了。这是 HarmonyOS 里的一个系统 API非常方便不需要自己写弹窗组件。如果要加一个步长调节功能既然step也标记了State我们可以在 UI 里加一个 Slider 组件来动态调节步长Slider({value:this.step,min:1,max:10,step:1}).onChange((value:number){this.stepvalue;})Text(步长${this.step})加了这几行之后用户拖动滑块改变步长滑块旁边的步长数字会实时更新而整个计数器的工作方式完全不受影响。这就是State的灵活性——多个状态变量各自独立互不干扰。五、深度技术原理底层是怎么做到的很多人到这里会好奇我就是写了个this.count它怎么就知道要去刷新界面这背后到底发生了什么这一节我们来把这个过程掰开揉碎了讲。第一层装饰器模式State本质上是一个装饰器Decorator。在 TypeScript/ArkTS 里装饰器的作用是在代码运行之前偷偷给你的变量或函数包一层逻辑。当你写State count: number 0时框架会创建一个代理对象把count的读写操作拦截下来每当你修改count的值这个代理就会收到通知收到通知后代理就会告诉 UI 框架“状态变了需要重新渲染”这就像一个中间人——你跟它打交道它再帮你去通知真正要做事的人。打个比方你去银行存钱把钱交给柜员柜员帮你办理存款业务。柜员就是那个代理你不需要自己跑去金库把现金放进去。State就是这个柜员的角色帮你处理通知界面刷新这件幕后工作。第二层响应式系统ArkUI 底层有一套响应式系统类似于 Vue 的响应式原理或者 React 的状态管理思路但实现方式不同。简单来说框架在编译阶段会分析你的State变量然后自动生成一套监听-通知机制。你写的this.count实际上是触发了一个 settersetter 里会调用一个内部的aboutToBeChanged()方法这个方法再触发 UI 重新渲染。具体来说整个流程是赋值时执行this.count 5触发 setterSetter 中调用框架内部的状态变更通知方法通知层框架收到通知开始执行重新渲染任务渲染层执行build()方法里的代码生成新的 UI 描述比对层将新的 UI 描述和旧的对比找出差异更新层只更新有差异的部分这就是增量渲染第三层增量渲染最神奇的地方在于UI 刷新的时候并不是把整个页面全部重新画一遍。框架会通过差异化比对类似 DOM Diff只更新变化了的部分。这就好比你去理发店染发发型师不会让你先把头发全剃光再重新长出来而是精准地只处理需要改变的部分。框架的增量渲染也是这个思路——它很聪明知道只更新真正变化了的地方。这个设计对性能的影响是巨大的。想象一下一个页面有一百个组件其中只有一个 Text 显示的文本变了。如果每次刷新都重建全部一百个组件那性能开销就是一百倍。增量渲染把这个开销降到了百分之一。对于复杂的列表页面这种优化带来的性能提升是肉眼可见的。打个比方计数器从 5 变成 6框架只需要把屏幕上显示 “5” 的那个 Text 组件改成显示 “6”而不需要重新构建整个 Column、整个 Button。这就好比你在一张纸上画了一幅画后来想改其中一根线条你不需要把整张纸扔掉重画你只需要擦掉那根线再画一根新的。框架就是这么高效的。简单总结原理链整个链路就是一条链修改变量 → 装饰器拦截 → 通知框架 → 差异化渲染 UI。你只需要记住第一步和最后一步中间那些脏活累活框架都帮你做了。这就是声明式 UI 的魅力——你描述要什么不用操心怎么做。用一句更简单的话总结State变量前面加个State变了界面自动更新就这么简单。所有复杂原理最终都是为了实现这个简单效果。最后再强调一点虽然原理说起来有拦截 → 通知 → 渲染这一串流程但在实际写代码的时候你感受到的只有改值 → 界面变这简单两步。这正是好框架的标准——把复杂性藏起来把简洁性留给开发者。ArkUI 的State正是做到了这一点。和其他平台做个对比如果你是从其他平台转过来的开发者对比一下会更容易理解平台状态管理方案特点FlutterStatefulWidgetsetState()需要切换到另一个类来处理状态代码分散React WebuseStatehook函数式组件hooks 模式React Native同上借助 Context 或 Redux大型应用需要额外状态库Android 原生LiveData/StateFlow(Jetpack Compose)Compose 也是声明式类似 ArkUIHarmonyOS ArkUIState装饰器原生支持语法简洁框架完成度高从对比里可以看出ArkUI 的State方案在简洁性上是很有优势的。它不需要你切换到另一个类不需要写 observer不需要写任何订阅代码只需要在变量前面加一个State就完事了。对于习惯了命令式编程的开发者来说这个学习曲线是最低的。FlutterReact-like用的是setState()调用后触发重建结合const构造和constwidget 可以做优化ReactWeb用的是useStatehook原理类似但 React 用的是虚拟 DOM diffingAndroid传统 View 系统用findViewById找控件然后手动setText()更新没有自动性HarmonyOSArkUI用State声明即响应框架自动处理 diffing 和更新可以看出HarmonyOS 的方案是这些方案里最简洁的——你只需要加一个State剩下的全交给框架。六、常见问题解答FAQQ1State 只能用于简单类型吗不是。State支持number、string、boolean等基本类型也支持class但建议配合Observed一起用、Array、Object等复杂类型。不过复杂类型用起来有讲究。如果你写Stateitems:string[][];this.items.push(new item);// ❌ 这种写法不会触发刷新这是因为push是在原数组上操作数组引用本身没变框架检测不到变化。正确写法是this.items[...this.items,new item];// ✅ 生成了新数组或者this.itemsthis.items.concat(new item);// ✅ concat 也生成新数组核心原则就是要创建一个新的引用框架才能检测到变化。Q2State 变量在子组件里能用吗能但要小心传递方式。State变量可以传递给子组件但需要通过参数传递。不过要注意单向数据流原则——子组件收到的是值的副本子组件修改不会影响父组件的状态。如果需要双向绑定要用Link装饰器。这个我们下一篇文章会专门讲。Q3修改变量后界面没反应是怎么回事常见原因有三个第一个忘了加State变量声明时忘记装饰器系统就不认识它变量改了界面当然不动。这是最常见的低级错误解决方法就是检查变量前面的State有没有漏掉。第二个在函数内部声明了局部变量局部变量不是响应式的State只能用在Component结构体外面。像这样写是错的build(){letcount0;// ❌ 局部变量加了 State 也没用// ...}正确写法是把变量放到build()方法外面Statecount:number0;// ✅ 在结构体级别build(){// ...}第三个赋值方式不对最典型的就是数组操作如上面 Q1 里讲的用了push/splice这种原地修改的方法而不是生成新数组。还有一种常见错误是对对象的某个属性赋值而不是替换整个对象——对于嵌套对象this.data.nested.value 5这种深层赋值需要配合Observed使用否则框架无法检测到变化。Q4所有变量都要加 State 吗千万不用。State是专门给会变、且一变界面就要跟着变的值用的。那些只读不变的常量、纯计算的中间变量完全不需要加装饰器。不加装饰器的好处是性能更好——框架不需要为这些变量维护响应式链路内存和计算开销都更小。加多了反而增加框架开销有点像为了防雨把整个城市都用防水布盖起来大可不必。记住一个简单的判断标准只有状态才需要 State。状态就是会变的数据。如果一个值从初始化到销毁都不变它就不是状态不需要加State。Q5State 和 Link 有什么区别这是两个最容易搞混的装饰器。简单说State是我的变量我来改——这个变量属于当前组件私有只有它自己能改Link是我接收了一个变量但我也想改它而且改了之后父组件也能看到——相当于双向绑定打个比方State就像你手里的遥控器只有你能按Link就像你把遥控器借给了室友室友按了电视也变了而且你也能看到电视变了因为你们共用同一个遥控器。在代码层面它们的区别是// 父组件StateparentCount:number0;// 传给孩子普通传值单向ChildComponent({count:this.parentCount})// 传给孩子双向绑定注意这个 $ 符号ChildComponent({count:$parentCount})子组件那边接收时// 普通传值子组件只能看不能改Propcount:number;// 双向绑定子组件可以改改了父组件也知道Linkcount:number;这里特别要注意$parentCount前面的$符号——它表示引用而不是值。传值this.parentCount传的是当前时刻的一个快照传引用$parentCount传的是指向原始变量的指针所以子组件改了之后父组件也能看到。这个$符号和 Swift 里的inout参数、React 里的onChange回调模式是一个意思只是语法不同而已。理解了本质各种语言的语法差异就不难掌握了。Q6State 变量能初始化为异步获取的值吗可以但要用对方法。直接在State声明时赋值不支持异步表达式比如await fetchData()因为装饰器初始化发生在同步阶段在异步数据返回之前组件就已经挂载了。正确做法是借助生命周期钩子aboutToAppear()Statedata:string;// 先给一个默认值aboutToAppear(){// 这里可以写异步逻辑fetchData().then((result){this.dataresult;// 数据返回后赋值界面会自动刷新})}这个aboutToAppear()是组件即将显示时调用的生命周期方法非常适合用来做初始化数据的异步加载。Q7State 能嵌套多层对象吗能但要配合Observed使用。关于Observed的详细内容我们会在后续文章里深入展开这里先预告一下它解决的是什么问题比如你有一个嵌套对象classInner{value:number0;}classOuter{inner:InnernewInner();}Statedata:OuternewOuter();this.data.inner.value5;// ❌ 嵌套层级的修改检测不到要让它能检测到需要用Observed装饰内部类ObservedclassInner{value:number0;}这样即使修改嵌套对象的属性界面也能正确响应。这个话题内容比较多以后我们会专门写文章讲Observed。Q8State 变量初始化有没有默认值要求有必须显式初始化。State装饰的变量必须在声明时直接赋予初始值不能只声明不赋值。这是因为State变量在组件创建时就需要有一个确定的初始值框架会用这个初始值来初始化响应式系统。如果你写了State count: number;然后在别的地方赋值ArkTS 编译器会报错。这个限制其实也是好事——它强制你把默认值是什么这件事想清楚而不是留到运行时才发现某个变量没有值导致 NaN 或者 undefined。好的默认值设计能大大减少运行时 bug。七、运行效果计数器页面运行示意整个过程无需任何手动刷新代码每次修改变量Text 组件里的数字就自动更新了。这就是State装饰器带来的声明式体验——你只管改值界面交给框架。调试小技巧如果你发现修改变量后界面没反应可以在 DevEco Studio 里打开实时检查面板查看组件树和当前的状态值。另外控制台日志里也会打印状态变化的信息便于追踪问题。还有一个实用的技巧在build()方法里加一行console.info(count this.count)每次界面渲染时你都能在日志里看到当前的count值是多少。如果点了一下按钮但日志没变化说明界面根本没重新渲染问题就定位在状态变更没有被检测到这个环节如果日志变了但界面没变说明问题出在渲染层。从一个按钮到一个完整页面计数器的例子虽然小但它展示了一个完整的数据驱动 UI 的闭环用户操作 → 状态变化 → 界面自动刷新。这个闭环是所有 HarmonyOS 应用的基本工作单元——无论你的应用多复杂都是由无数个这样的闭环组成的。学会了State你就掌握了构建 HarmonyOS 应用最核心的能力。从一个按钮到一个完整页面区别只在于状态变量的数量和业务逻辑的复杂程度底层机制完全一样。所以别小看这个计数器案例它是所有复杂应用的起点。八、扩展方向计数器虽然简单但它是理解整个 HarmonyOS 状态管理体系的起点。沿着这条路你可以继续探索以下几个方向每个方向都是一个全新的知识领域1. 加个步长调节器在现有基础上加一个滑块让用户可以调节每次加减的步长1、2、5、10。这会让你更好地理解多个State变量之间如何协同工作。而且你会发现由于step也标记了State调节步长完全不需要改动任何其他代码框架自动处理好了。2. 引入 Link 做双向绑定把增加/减少的逻辑拆到一个子组件里用Link把状态从父组件传下去。这样你就能亲身体验State和Link的配合理解单向数据流的含义。实话说Link是State最重要的搭档。很多新手学完State就停住了觉得自己会了但一做稍微复杂点的页面就卡住了——就是因为还没学会State和Link配合使用。等你搞懂了Link你就能写出组件化、可复用的界面了。3. 接入 Observed 处理复杂对象当你的状态从简单数字变成一个对象比如{ count: 0, history: [], maxValue: 100 }就需要Observed配合使用了。它能让嵌套对象也具备响应式能力这是构建真实业务应用必不可少的一环。4. 用 Prop 做纯展示传递如果子组件只是看状态不需要改状态用Prop更合适。它是单向数据流不会产生意外的状态污染。Prop的一个典型应用场景是一个展示用户头像和昵称的卡片组件它只需要显示数据不需要修改数据这时候用Prop就很合适。5. 结合网络请求做真实数据把静态计数器换成真实的数据展示比如从接口拉取一个列表并展示。用户在文本框输入搜索词列表就自动过滤。这个过程中你需要理解aboutToAppear生命周期、异步数据的处理方式以及如何优雅地管理加载中和加载失败的状态。这类需求在实际工作中最常见。比如做一个天气 App你在文本框里输入城市名点搜索后端返回天气数据数据一变界面就刷新。这些都建立在State能正确触发刷新的基础上。6. 了解其他状态装饰器HarmonyOS 的状态管理家族很大除了State还有Link、Prop、Provide、Consume、ObjectLink等等。计数器案例是入口吃透了之后再学其他的就会发现它们其实是一套相互配合的系统各有各的用途共同构成了 HarmonyOS 的响应式状态管理生态。6. 了解其他状态装饰器HarmonyOS 的状态管理家族很大除了State还有Link、Prop、Provide、Consume、ObjectLink等等。计数器案例是入口吃透了之后再学其他的就会发现它们其实是一套相互配合的系统各有各的用途共同构成了 HarmonyOS 的响应式状态管理生态。7. 探索性能优化方向当你的状态变量很多、界面很复杂的时候响应式刷新的性能问题就会显现出来。届时你需要了解 ArkUI 的渲染优化机制比如LazyForEach懒加载列表、Reusable组件复用等技巧。这些能让你的应用在低配置设备上依然流畅运行。8. 学习状态管理设计模式当你从单个页面跨越到多页面应用时简单的State就不够用了。这时候你需要了解应用级别的状态管理——如何在多个页面之间共享数据、如何管理全局状态、如何处理页面跳转时的数据持久化等等。这些话题涉及架构设计是从小工到工匠的必经之路。一个建议是先把手头的State用熟不要一开始就上 Redux/Vuex 那一套。状态管理的复杂度应该和项目的复杂度相匹配。计数器就用State购物车用StateLink再大一点用Provide/Consume真正到了大型应用再用全局状态管理。渐进式地学习比一开始就追求最佳实践要实在得多。