react、vue的响应式原理 上文提到修改数据时,react需要调用setState方法,而vue直接修改变量就行。看起来只是两个框架的用法不同罢了,但响应式原理正在于此。 从底层实现来看修改数据:在react中,组件的状态是不能被修改的,setState没有修改原来那块内存中的变量,而是去新开辟一块内存;而vue则是直接修改保存状态的那块原始内存。 所以经常能看到react相关的文章里经常会出现一个词"immutable",翻译过来就是不可变的。 数据修改了,接下来要解决视图的更新:react中,调用setState方法后,会自顶向下重新渲染组件,自顶向下的含义是,该组件以及它的子组件全部需要渲染;而vue使用Object.defineProperty(vue@3迁移到了Proxy)对数据的设置(setter)和获取(getter)做了劫持,也就是说,vue能准确知道视图模版中哪一块用到了这个数据,并且在这个数据修改时,告诉这个视图,你需要重新渲染了。 所以当一个数据改变,react的组件渲染是很消耗性能的——父组件的状态更新了,所有的子组件得跟着一起渲染,它不能像vue一样,精确到当前组件的粒度。 总结 react因为先天的不足——无法精确更新,所以需要react fiber把组件渲染工作切片;而vue基于数据劫持,更新粒度很小,没有这个压力; react fiber这种数据结构使得节点可以回溯到其父节点,只要保留下中断的节点索引,就可以恢复之前的工作进度;

补充

补充:Vue 不需要 Fiber,本质是因为它的「细粒度响应式 + 模板编译期标记」已经将更新粒度控制到了「依赖该数据的最小组件」,不必像 React 那样在运行时做整棵组件树的协调与中断。

对比要点:

  • 更新粒度:React 自顶向下重新渲染,需要 Fiber 把渲染切片、可中断以避免卡顿;Vue 借助 Proxy 收集依赖,按组件粒度精确更新。
  • 数据可变 vs 不可变:React 推崇 immutable 方便时间旅行和并发安全;Vue 直接修改原始内存,靠依赖追踪保证视图同步。
  • 调度复杂度:Vue 不需要 Scheduler 协调「同步 vs 异步 vs transition」优先级,因为大部分更新是同步的;React 16+ 在并发模式下要处理 lane 优先级。
  • 代价:Vue 的细粒度响应式在大型数据结构上有内存开销;React 的不可变 + diff 在极大组件树时反而更可控。

补充:Vue3 在编译器静态标记(patchFlag)加持下,diff 阶段几乎只对动态节点做处理,这也是它「无 Fiber 也很快」的重要原因。