乐趣区

关于javascript:对比react和vue的diff算法

最近从 vue 应用转到 react 应用,

之前钻研过 vue 的 diff 算法,闲来看了看 react 的 diff 源码,写一点本人的见解

1.vue 的 diff 算法

diff 算法产生在虚构 dom 上

判断是否同一个节点:selector 和 key 都要一样

diff 规定:

  1. 只比拟同层的节点,不同层不做比拟。删除原节点,并且新建插入更新节点(理论开发中很少遇到)
  2. 新旧节点是同层节点,但不是同一个节点,不做精细化比拟。删除原节点,并且新建插入更新节点(理论开发中很少遇到)
  3. 新旧节点是同层节点,也是同一个节点,须要做精细化比拟

diff 的精细化比拟策略

  1. 新的头部子节点,旧的头部子节点
  2. 新的尾部子节点,旧的尾部子节点
  3. 新的尾部子节点,旧的头部子节点
  4. 新的头部子节点,旧的尾部子节点

如果条件 1 满足,新旧节点头部指针往后移。

如果条件 2 满足,新旧节点尾部指针往前移。判断是否新的子节点先循环完(头尾地位指针判断),是:就是删除了节点,否:新增了节点,新增的节点依照条件 4 增加

如果条件 3 满足,须要挪动新的头部子节点到旧的尾部子节点前面

如果条件 4 满足,须要挪动新的头部子节点到旧的头部子节点后面

如果 4 种都未匹配到,并且指针条件未满足,须要 loop 匹配

vue 在把被挪动的节点和匹配的节点设置为 undefined

2.react 的 diff 算法

从左往右顺次比照,利用元素的 index 和标识 lastIndex 进行比拟,如果满足 index < lastIndex 就挪动元素,删除和增加则各自依照规定调整

跨层不比拟,同层比拟,跟 vue 一样

diff 策略

新节点的地位是 lastIndex,旧节点的地位是 index。从新的节点中顺次读取节点索引,比照旧的节点数据索引

  1. 不满足 index < lastIndex 的条件,不挪动;满足 index < lastIndex 的条件,挪动节点。
  2. 每一次比拟都须要从新设置 lastIndex=(index,lastIndex) 中的较大数
  3. 挪动的节点在前一个被操作的节点前面
  4. 如果从新的节点汇合获取的节点在旧节点汇合未找到,就是新增,lastIndex 为上一次的值不变
  5. 如果新的节点汇合遍历完了,旧节点还有值就是删除,loop 删除掉就行

最恶心的状况:如果把最初一个元素移到最后面,react 会顺次挪动节点向后

3. 比照

类似的中央:vue 和 react 的 diff 算法,都是不进行跨层级比拟,只做同级比拟。

不同点:

  1. vue 会在 patch 函数中给被操作的节点打补丁(undefined),在 diff 的时候更清晰
  2. vue 比照节点,当节点元素类型雷同,然而 className 不同时,认为是不同类型的元素,删除从新创立;而 react 则认为是同类型节点,进行批改操作
  3. diff 策略,vue 的性能优于 react
退出移动版