react中diff算法和vue中的diff算法区别。

vue和react框架,核心算法都是diff算法,什么叫diff算法可能有一部分人都是没有深究的,今天梳理一下vue和react的diff算法,有什么却别。

什么是虚拟dom

虚拟dom,就是我们在页面上展示的dom结构叫做dom树,我们把数据和将要渲染的代码模拟dom结构生成的对象类型的数据结构,就叫虚拟dom树,将真实的DOM数据抽取出来,以对象的形式模拟树形结构,我们先根据真实dom生成一课virtual DOM,当virtual DOM某个节点数据改变后会生成一个新的Vnode,然后 Vnode 和 oldVnode 作对比,发现有不一样的地方就直接修改在真实的DOM上,然后使 oldVnode 的值为 Vnode 。

什么叫做diff算法

原始的diff算法

1.全量比较:原始的diff算法通常是直接比较两棵树的所有节点,无论节点是否有变化。这意味着每次更新都要遍历整个DOM结构,进行全量比较。

2.粗粒度更新:每次更新时,如果有任何差异,原始算法会直接替换整个子树或者执行全量更新,没有办法区分出具体哪些节点发生了变化。

3.性能问题:原始算法的性能问题主要表现在频繁的DOM操作和重绘/重排操作,即使只有少量节点变化,也可能导致整个页面的重新渲染,性能不佳。

4.复杂度高:随着页面结构复杂度增加,原始算法的复杂度会随之增加,难以应对大规模数据更新和高频率状态变更。

优化后的diff算法(如React,Vue框架使用的算法):


1.部分更新:优化后的diff算法会先生成新旧两棵虚拟DOM树,然后通过一系列优化策略(如双端比较、使用key优化列表更新等)只比较变化的部分,而不是全量比较。

2.精确度高:算法能够识别具体哪些节点发生了变化,从而只对需要更新的部分进行DOM操作,避免了不必要的操作和页面重绘。

3.性能优化:优化后的算法能够减少不必要的DOM操作和重绘/重排次数,提升了页面的渲染效率和响应速度,尤其在大规模数据更新和高频状态变更时表现更为出色

Vue的diff算法

在Vue中,父子组件之间的diff算法是互相独立的。这意味着,Vue的diff算法在比较和更新件的虚拟DOM树时,不会受到子组件虚拟DOM树的影响,反之亦然。

父子组件的虚拟DOM独立性:

1.独立的虚拟DOM树:每个Vue组件都有自己独立的虚拟DOM树。父组件的状态变化只会影响到父组件自身的虚拟DOM树,而不会直接影响到子组件的虚拟DOM树。

2.组件更新优化:当父组件的状态发生变化时,Vue会重新计算和比较父组件的虚拟DOM树,然后根据比较的结果更新实际的DOM。这个过程中,Vue会忽略掉子组件内部虚拟DOM树的比较和更新,除非子组件的props或者自身状态也发生变化。

3.Diff算法的应用范围:Vue的diff算法主要应用于每个组件的虚拟DOM树内部。父组件和子组件之间的虚拟DOM树是相互独立的,所以它们的更新过程也是分开处理的。

例子说明:

假设有一个父组件和一个子组件,它们分别是ParentChild,并且在父组件的模板中引用了子组件:

<template>
  <div>
    <Child :prop="someValue" />
  </div>
</template>

<script>
import Child from './Child.vue';

export default {
  components: {
    Child
  },
  data() {
    return {
      someValue: 'initial'
    };
  },
  methods: {
    updateValue() {
      this.someValue = 'updated';
    }
  }
}
</script>

vue的diff算法的比较规则:新旧列表的两端对比:

在 Vue 中,diff 算法的比较规则主要指的是在更新虚拟DOM时,Vue 采用的一种优化策略,即双端比较(Two-Ended Diffing)。这种策略可以有效地减少需要比较的节点数量,从而提高 diff 算法的效率。

双端比较的基本原理

1.初始化:Vue 在更新虚拟DOM时,会同时从新旧节点列表的头部和尾部设置两个指针,分别称为 oldStartIdx, oldEndIdx, newStartIdx, newEndIdx

2.比较过程:Vue 将新旧节点列表的头部和尾部的节点进行两两比较:

如果头部节点匹配,则进行更新操作,并将指针向后移动。

如果尾部节点匹配,则进行更新操作,并将指针向前移动。

如果头部节点不匹配,则尝试与旧列表的尾部节点进行比较,以此类推。

3.优化匹配:这种双端比较的策略可以有效地在较少的比较操作中找到最优的匹配节点,从而减少需要执行的更新操作,避免不必要的DOM操作。

4.处理特殊情况:在比较过程中,还需要处理一些特殊情况,如新旧列表长度不一致时的节点删除或添加,以及列表中存在 key 属性时的优化比较。

优点:提升性能: 双端比较策略相比传统的单向比较,可以减少比较的次数和执行的DOM更新操作,特别是在处理大型列表或数据变更频繁的场景下效果显著。

避免全量比较: Vue 的 diff 算法通过双端比较,能够更快速地找到最小化更新的路径,避免了每次更新都进行全量比较和重新渲染。

利用现代浏览器优势: 双端比较策略利用了现代浏览器在DOM操作上的优化能力,例如批量更新和异步渲染机制,进一步提升了页面的性能和响应速度。

vue的diff算法的移动规则:不同情况的移动规则不同

如果列表中的节点没有设置 key 属性,Vue 的 diff 算法会采用最小移动的原则通过索引移动: 如果新旧列表中的节点位置改变了,但节点本身没有变化(即节点的内容和属性没有变化),Vue 将尽可能复用已存在的 DOM 节点,只进行位置的移动操作,而不是重新创建和销毁节点。

key 的情况

Key 的重要性: key 属性帮助 Vue 管理每个节点的身份,以便进行精确的比较和移动操作。在比较过程中,Vue 会根据 key 来判断节点的增删改移动。

移动操作的优化: 如果节点位置发生变化,但具有相同 key 的节点在新旧列表中仍存在,Vue 将尝试复用这些节点,而不是直接销毁和重新创建。这样可以保持节点的状态和事件处理程序,避免不必要的更新操作。

特殊情况的处理:

新节点和旧节点的对比:新增节点: 如果新列表中有新增的节点,Vue 会直接创建并插入到正确的位置。

删除节点: 如果旧列表中有被删除的节点,Vue 会将这些节点标记为需要移除。

节点顺序变化:Vue 会根据比较结果,尽可能少地移动和调整节点的顺序,避免不必要的DOM操作,提升性能。

React的diff算法

1.react的diff算法对父子兄弟组件的影响:

1. 父子组件之间的影响:

组件更新传递: 当父组件的状态或属性发生变化时,React 会重新计算父组件的虚拟DOM树。这可能导致父组件的 render 方法被调用,生成一个新的虚拟DOM树。

子组件的比较和更新: React 会比较新旧父组件的虚拟DOM树,识别出子组件是否需要进行更新。如果子组件的 props 或 state 发生了变化,或者父组件的 render 返回的虚拟DOM发生了变化,React 将更新子组件的虚拟DOM树。

DOM更新: 最终,React 会根据比较的结果生成一系列的更新指令,将变更应用到实际的DOM上。这个过程是通过最小化DOM操作来提高性能和渲染效率的。

2. 兄弟组件之间的影响:独立更新:

独立更新: React 在更新兄弟组件时,会独立处理每个组件的虚拟DOM树。即使同一个父组件的多个子组件同时需要更新,React 也会分别计算每个子组件的变化,并且独立生成和应用更新指令。

DOM更新时机: 虽然在同一个更新周期内,React 会批量处理所有的更新指令,但是每个兄弟组件的更新是相互独立的,不会互相影响。

vue与react的diff比较

1.vue和react的diff算法,都是忽略跨级比较,只做同级比较。vue diff时调动patch函数,参数是vnode和oldVnode,分别代表新旧节点。
2.vue对比节点。当节点元素相同,但是classname不同,认为是不同类型的元素,删除重建,而react认为是同类型节点,只是修改节点属性。
3.vue的列表对比,采用的是两端到中间比对的方式,而react采用的是从左到右依次对比的方式。当一个集合只是把最后一个节点移到了第一个,react会把前面的节点依次移动,而vue只会把最后一个节点移到第一个

总结:

1.react-diff: 遍历法对比
2.vue-diff: 双端对比
3.总体来讲vue的diff算法更佳,总体规律就是找到新节点所对应的旧节点列表中的节点,而后给真实的对应的dom移动到正确的位置
4.vue3.0的diff算法还没有梳理过,以后可以在说vue3.0其他东西的时候带上,一些更改的地方该了解的还是要了解的

  • 18
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值