vue和react的相同点和区别

1,246 阅读11分钟

Vue和React作为当前前端开发领域中的两大主流框架,它们之间既有相似之处,也存在显著的区别。以下是它们之间的详细对比:

相同点

  1. 虚拟DOM

    • Vue和React都采用了虚拟DOM技术。它们都会创建一个虚拟的DOM树,并与真实DOM树进行对比,只更新有变化的部分,从而大大提高了页面的渲染性能。
  2. 组件化

    • 两者都支持组件化开发,将UI拆分为可复用的组件,有助于构建大型和可维护的应用程序。
    • 两者都支持父子组件之间的数据传递(props),并且都强调单向数据流(尽管Vue通过v-model等机制实现了双向数据绑定,但本质上也是单向数据流的一种实现)。
  3. 数据驱动视图

    • Vue和React都是数据驱动视图的框架,当数据发生变化时,视图会自动更新。
  4. 服务端渲染

    • 两者都支持服务端渲染(SSR),有助于改善SEO和首屏加载速度。
  5. 构建工具

    • Vue和React都有自己的构建工具,可以快速搭建开发环境。Vue对应的是vue-cli,而React则可以使用Create React App (CRA)。

区别

  1. 实现原理

    • Vue采用组件响应式思想,通过getter/setter以及一些函数的劫持,能精确知道数据的变化,并触发相应的视图更新。
    • React则采用函数式组件思想,通过diff算法比较新旧虚拟DOM的差异,然后更新真实DOM。React 16还引入了Fiber架构,将DOM树微观化为链表,提高了diff算法的效率。
  2. 设计结构

    • Vue使用的是可变数据,数据由data属性在Vue对象中进行管理。
    • React更强调数据的不可变性,通过setState()方法更新状态。
  3. 数据流

    • Vue通过v-model等机制实现了双向数据绑定,使得数据模型和视图之间的同步更加直接。
    • React则采用单向数据流,通过props将数据从父组件传递到子组件,并通过回调函数或Context等方式实现子组件到父组件的数据传递。
  4. 模板语法

    • Vue鼓励使用HTML模板语法,写起来更接近于常规的HTML结构,同时支持在模板中直接编写CSS和JavaScript。
    • React则推荐使用JSX语法,将HTML和CSS都写进JavaScript中,实现了“all in js”的理念。
  5. 状态管理

    • Vue的状态管理可以通过Vuex等库实现,但Vue的核心也提供了一定程度的状态管理能力。
    • React的状态管理则更多依赖于Redux等第三方库。
  6. 框架本质

    • Vue是一个渐进式框架,旨在降低前端开发的门槛,让更多的人能够更快地上手开发。它使用了MVVM框架,由MVC框架发展而来。
    • React则是一个前端组件化框架,由后端组件化发展而来。它更关注于UI的开发,提供了丰富的UI组件和API。
  7. 学习曲线

    • Vue被认为对新手友好,其文档清晰且框架设计较为直观。
    • React由于其更“裸露”的性质和丰富的生态系统,可能需要更多的学习时间。

总结来说,Vue和React在虚拟DOM、组件化、数据驱动视图等方面具有相同点,但在实现原理、设计结构、数据流、模板语法、状态管理、框架本质和学习曲线等方面存在显著的区别。开发者可以根据项目的具体需求和个人偏好选择适合的框架。

Vue和React的Diff算法是两者在更新DOM时用于比较虚拟DOM和真实DOM差异的重要机制。以下是它们Diff算法的详细介绍:

Vue的Diff算法

  1. 节点对比

    • Vue的Diff算法会尽量复用节点,而不是频繁地创建和销毁节点。它首先会进行同层级的节点对比,如果节点元素类型相同,则认为是相同的节点,并会进行进一步的子节点对比。
    • 如果节点元素类型不同,Vue会认为是不同类型的元素,会进行删除重建。但值得注意的是,对于className等属性的不同,Vue并不会认为是不同类型的元素,而只是修改这些属性。
  2. 列表比对

    • Vue的列表比对采用的是首尾指针法。当一个集合只是把最后一个节点移动到了第一个时,Vue只会把最后一个节点移动到第一个,而不会重新渲染整个列表。这种策略使得Vue在列表更新时具有更高的效率。
  3. 响应式系统

    • Vue的Diff算法与其响应式系统紧密相关。当数据发生变化时,Vue的响应式系统会精确地知道哪些节点需要更新,从而避免了不必要的比较和渲染。

React的Diff算法

  1. Tree Diff

    • React通过制定策略,将O(n^3)复杂度的问题转换成O(n)复杂度的问题。React对树的算法进行了优化,即只会对同一层次的节点进行比较,而不是递归地比较整棵树。
    • React通过updateDepth对Virtual DOM树进行层级控制,只会对相同父节点下的所有子节点进行比较。当发现节点已经不存在时,该节点及其子节点会被完全删除掉,不会用于进一步的比较。
  2. Element Diff

    • 对于同一层次的节点,React会进行Element Diff。如果节点类型不同,React会销毁旧的节点并创建新的节点。如果节点类型相同,React会进行进一步的属性对比和子节点对比。
  3. Key的作用

    • 在列表渲染中,React通过key属性来识别每个节点,从而进行高效的复用和更新。当列表项的位置发生变化时,React会根据key来找到对应的节点并进行移动,而不是重新渲染整个列表。
  4. Fiber架构

    • React 16引入了Fiber架构,将递归的无法中断的更新重构为异步的可中断更新。Fiber节点上能访问到父节点、子节点、兄弟节点,使得即使渲染被打断了,也可以恢复查找未处理的节点。这进一步提高了React的渲染效率和稳定性。

总结

Vue和React的Diff算法在策略和实现上有所不同。Vue的Diff算法更加关注节点的复用和列表的高效更新,而React的Diff算法则更加关注树形结构的优化和Fiber架构的引入。两者都通过各自的方式提高了DOM更新的效率和性能。

React 16引入的Fiber架构

React 16引入了Fiber架构,这是一种全新的协调引擎,通过增量渲染(拆分成多个小任务执行)、优先级调度(确保高优先级任务快速响应)和可中断恢复(允许在任务之间暂停和恢复)等机制,提高了React的性能和响应速度,使其能够更高效地处理复杂和高频的用户交互。

  1. 背景

    • 在React 16之前,React的渲染过程是通过一个称为“Stack Reconciler”的递归过程来完成的。这个过程在大型项目或复杂组件树中可能导致性能问题,因为它会长时间占用浏览器的主线程,导致页面卡顿和用户体验下降。
  2. Fiber架构的引入

    • 为了解决这些问题,React 16引入了Fiber架构。Fiber是一个将渲染工作分成多个小的工作单元(称为“Fiber”)的架构,这些工作单元可以在多个帧中执行。这种拆分使得React能够在工作单元之间暂停和恢复,从而避免长时间占用主线程。
  3. 主要特点

    • 增量渲染:Fiber将渲染工作分成多个小的工作单元,这些单元可以在多个帧中执行。由于分成了更小的任务单元,在这些任务单元之间可以停顿,从而允许浏览器执行其他任务,如用户输入或动画。
    • 优先级调度:不同的任务根据其重要性被赋予不同的优先级。例如,用户输入等高优先级任务可以快速响应,而低优先级的任务(如数据获取)则可以在主线程空闲时执行。
    • 恢复和暂停:React可以在处理完一个工作单元后中断,检查是否有更高优先级的任务需要处理。如果有,则优先处理高优先级任务;否则,继续处理剩余的渲染任务。
  4. 两阶段 & 两棵树

    • 调度阶段(Reconciliation Phase) :在这一阶段,React会计算需要更新的组件和对应的状态变更。这个阶段是可以被中断的,React会根据优先级逐步处理更新任务。
    • 提交阶段(Commit Phase) :一旦调度阶段完成,提交阶段会将更新应用到实际的DOM中。这个阶段是同步的,React会确保所有的DOM变更在一次帧内完成。
    • 两棵树:Fiber架构在内存中包含了两棵树,一棵是当前树(已经渲染完成的树),另一棵是工作树(Work-in-Progress Tree)。这两棵树互相替换进行状态的更新。
  5. 实现方式

    • React重新设计了一种链表的vdom结构,每个节点称之为一个Fiber。每个Fiber包含了一些属性,如stateNode(状态节点)、child(子节点)、return(表示当前节点处理完毕后,应该向谁提交自己的成果,即effect list)、sibling(兄弟节点)等。这种链表结构使得每一个Fiber都可以访问到整棵树。
  6. 性能提升

    • 通过Fiber架构,React能够更好地处理复杂和高频的用户交互,减少页面卡顿,提升用户体验。特别是对于动画和交互频繁的应用场景,Fiber架构能够带来显著的性能提升。

综上所述,React 16引入的Fiber架构通过增量渲染、优先级调度、恢复和暂停等机制,实现了更细粒度的更新和高效的调度,从而提升了React的性能和用户体验。

vue2.xvuex3.x 渲染器的 diff 算法分别说一下?

参考答案:

简单来说,diff 算法有以下过程

  • 同级比较,再比较子节点
  • 先判断一方有子节点一方没有子节点的情况(如果新的 children 没有子节点,将旧的子节点移除)
  • 比较都有子节点的情况(核心 diff)
  • 递归比较子节点

正常 Diff 两个树的时间复杂度是 O(n^3),但实际情况下我们很少会进行跨层级的移动 DOM,所以 Vue 将 Diff 进行了优化,从O(n^3) -> O(n),只有当新旧 children 都为多个子节点时才需要用核心的 Diff 算法进行同层级比较。

Vue2 的核心 Diff 算法采用了双端比较的算法,同时从新旧 children 的两端开始进行比较,借助 key 值找到可复用的节点,再进行相关操作。相比 React 的 Diff 算法,同样情况下可以减少移动节点次数,减少不必要的性能损耗,更加的优雅。

Vue3.x 借鉴了 ivi 算法和 inferno 算法

在创建 VNode 时就确定其类型,以及在 mount/patch 的过程中采用位运算来判断一个 VNode 的类型,在这个基础之上再配合核心的 Diff 算法,使得性能上较 Vue2.x 有了提升。该算法中还运用了动态规划的思想求解最长递归子序列。

React的Diff算法简述:

  1. 三大策略:采用Tree Diff、Component Diff、Element Diff策略,分别针对树层级、组件层级和元素层级进行优化。
  2. 层级控制:Tree Diff忽略跨层级操作,只比较同层级节点,降低复杂度至O(n)。
  3. 组件优化:Component Diff针对同类型组件进行子树比较,不同类型则直接替换,支持shouldComponentUpdate优化。
  4. 元素复用:Element Diff通过唯一key标识节点,实现高效复用和移动,减少不必要的DOM操作。