文章目录前言核心机制依赖收集代码实现派发更新只动该动的V1 的局限观察粒度粗核心代码V2 的改进精确到属性完整示例为什么有时候变了却不刷新性能启示常见误区小白必踩完整可运行示例响应式本质代码解析写在最后前言前面那篇状态驱动 UI讲了现象改了Local界面就变。这篇往深里挖一层框架到底是怎么知道该重画哪的理解这个你就能写出性能更好的代码也少踩改了不变变错了地方的坑。我用大白话把依赖收集 派发更新这套机制讲透。核心机制依赖收集框架在第一次build()时会偷偷记录“这个 Text 用到了count”。这个动作叫依赖收集。代码实现Localcount:number0build(){Column(){Text(countthis.count)// 框架记录此 Text 依赖 countText(固定文字)// 此 Text 不依赖任何状态}}框架心里有本账组件/节点依赖的状态Text1countText2无派发更新只动该动的当你this.count 1框架查账本谁依赖count只有 Text1。于是只重画 Text1Text2 纹丝不动。这就是响应式高效的原因——精准更新而不是整页重画。对比命令式你得一长串text1.setText(...)手动改。声明式下框架替你定位谁该变。V1 的局限观察粒度粗老版StateV1观察的是整个对象。比如核心代码Stateuser:{name:string,age:number}{name:A,age:1}// 改深层属性this.user.age2// V1 可能不触发更新需 ObservedV1 只盯着user这个引用你改user.age没换引用它发现不了。要ObservedObjectLink才行写法很绕。V2 的改进精确到属性V2Local等原生支持深层属性监听完整示例Localuser:{name:string,age:number}{name:A,age:1}this.user.age2// V2 直接触发更新 ✅框架对每个属性单独收集依赖改age就只更新用到age的节点。深层嵌套对象也照常工作不用Observed。为什么有时候变了却不刷新回到根源通常三个原因变量没加状态装饰器 → 框架没收集它的依赖 → 改了不重画。V1 下改了深层属性没用Observed→ 框架没监听到。在build()执行期间改状态 → 可能引发重复渲染或丢失更新。性能启示状态拆得越细更新越精准。一个超大Local对象改其中一个字段也会让所有依赖它的节点重画。大数据、不需要驱动 UI 的用普通变量别挂状态装饰器省去无谓的依赖追踪。常见误区小白必踩误区说明变量不加装饰器框架没收集它的依赖改了不重画。想变就加Local/State。V1 深层忘Observed改对象里字段不刷新换 V2 原生支持深层监听。在build里改状态会触发重复渲染初始化放aboutToAppear更新放事件里。下面这段代码可以直接复制到 DevEco Studio 里运行。建议你边读边敲改一改文末「动手改一改」里的参数亲眼看看效果。完整可运行示例响应式本质State被读取的地方会注册成「依赖」状态变就重渲染。代码解析// 只有「读取了 State」的 UI 节点才会在更新时被重新求值EntryComponentstruct Reactive{Statea:number0Stateb:number0build(){Column({space:16}){Text(athis.a)// 依赖 aText(bthis.b)// 依赖 bText(sum(this.athis.b))// 依赖 a 和 bButton(a1).onClick((){this.a})Button(b1).onClick((){this.b})}.padding(20)}}你会看到什么点a1只有「a」和「sum」两段文字更新b不动——因为框架知道这俩节点没读a跳过重渲染。这就是响应式「精准更新」的本质。动手改一改把sum改成独立State s用a1时同时s ab对比两种更新粒度。在Text里加console.info点按钮看哪些节点被重新求值。把State换成普通let点按钮发现界面不更新——印证「非响应式数据不驱动 UI」。写在最后响应式本质就是两步build 时收集依赖状态变时按依赖精准更新。V2 把观察粒度从对象细化到属性深层更新不再头疼。懂了这套你看Local/Param就不只是能跑而是知道它背后在替我盯哪个变量、重画哪块 UI。写代码时会更克制地拆分状态性能自然更好。