前言

哈喽,大家好,我是 Baker !🎉

对于前端的 Vue 和 React 相信大家并不陌生,这两个库有着截然不同的设计思想和发展目标,对于我们上层使用者来说,研究它们的差异不仅让我们更加深入的去理解这些库的设计思想,也能帮助我们在开发中更有依据的去选择合适的框架。

本篇文章就两者的更新机制来浅淡一下它们的区别,因为是浅淡并且也受限于篇幅,所以这里并不会就某些技术细节进行展开,如果大家想要深入去了解两者技术的实现,可以尝试去读一下源码,或者期待一波博主后续的更新🌹

因为不涉及技术细节,大家放轻松,悠闲自在的观看即可。

浅谈 React 与 Vue 更新机制的差异-LMLPHP

好啦,让我们开始吧!

Vue 更新机制

Vue 使用著名的响应式系统收集依赖派发更新,当模板中数据发生变化时,组件的 render 函数会被作为数据的依赖而被触发,只不过这个触发并不是立刻的,因为模板中会引用很多数据,render 同时是这些所有数据的依赖项,如果 render 每次都立刻执行,则会造成多次重复渲染而消耗性能。

实际上 render 是被 update 调用的,而 update 又是 Watcher 调用的,而 Watcher 在收到 Dep 的派发更新时会把自身交给 Scheduler ,由 Scheduler 负责对其去重并通过 nextTick() 将这些 Watcher 包装成微任务放入到事件循环中等待调用。

render 执行输出的结果是一颗新的虚拟 DOM 树,然后 update 会通过 patch 函数将它与旧的虚拟 DOM 树进行对比,diff 和真实 DOM 的操作过程既是在 patch 函数中进行。

所以,其实 Vue 的整个更新任务(构建虚拟 DOM ,diff,操作真实 DOM)可以算作一个整体,这个整体被当作微任务来处理,这也就是 Vue 异步更新的原理。

最后附上一张 Vue 官方文档的流程图:

浅谈 React 与 Vue 更新机制的差异-LMLPHP

React 更新机制

这里以 React16 之后的 Fiber 架构为例。

React 没有 Vue 的响应式系统,它的更新主要是靠用户手动的调用副作用函数(比如 setState 等)来触发( Vue 则是系统自动触发)。所有的更新任务(如调用 setState )会被 render 阶段的 Scheduer 进行调度,它会将多次的 setState 调用合并为一次更新操作,render 阶段可以随时被打断(如遇到高优先级任务、当前事件循环没有足够的时间了、发生了其它错误等)。

Scheduer 调度器负责对任务进行调度,内部会通过任务的优先级(会通过一系列的优先级设置任务的 delay ),以及当前事件循环空闲的时间等来判断当前任务是否可以执行,如果可以执行则会通过 MessageChannel 将任务包装成一个宏任务推入到事件循环当中等待执行,在任务执行时通过 render 阶段的 Reconciler 来进行协调。

Reconciler 通过递和归两个阶段来创建新的 Fiber Tree 和进行副作用的收集(这个副作用指的是 DOM 的更新操作)( diff 发生在此),至此 render 阶段结束,之后就来到了 commit 阶段,该阶段只有一个 Readerer 执行,并且是同步执行,Readerer 主要就是根据 Fiber Tree 标记的副作用来进行真实 DOM 的创建、更新和删除操作。

浅谈 React 与 Vue 更新机制的差异-LMLPHP

区别

其实大体上 Vue 和 React 的更新机制都是构建虚拟DOM、diff、操作真实DOM这三个主要过程,它们的主要区别主要体现在触发更新的机制和一些细节上:

  • 触发更新机制:Vue 是通过响应式系统自动及时的进行触发,而 React 则是通过用户更改状态的操作然后进行一系列调度来触发更新。

  • 任务的区别:Vue 会将任务包装成微任务,而 React 则是将其包装成宏任务。

  • diff 算法的不同:Vue 采用双端对比,而 React 使用的是 Reconciliation 算法。

结语

还是那句话,本篇文章只是浅淡,Vue 和 React 的更新机制非常复杂,其中涉及的知识点很多,比如 Vue 的响应式原理、Vue 双端 diff 流程、React Fiber 架构、Fiber 双缓冲、React Reconciler 递和归两阶段流程等等。

本文简单梳理了一下它们更新机制的整体流程,希望能基于此来为大家展开一个清晰的脉络,如果在阅读过程中发现了问题,欢迎评论区留言交流!

如果本篇文章对你起到了帮助,还请大家不要吝啬手中的点赞、评论、收藏和关注,我们下次再见!

09-24 07:34