最近从vue使用转到react使用,
之前研究过vue的diff算法,闲来看了看react的diff源码,写一点自己的见解
1.vue的diff算法
diff算法发生在虚拟dom上
判断是否同一个节点:selector和key都要一样
diff规则:
- 只比较同层的节点,不同层不做比较。删除原节点,并且新建插入更新节点(实际开发中很少遇到)
- 新旧节点是同层节点,但不是同一个节点,不做精细化比较。删除原节点,并且新建插入更新节点(实际开发中很少遇到)
- 新旧节点是同层节点,也是同一个节点,需要做精细化比较
diff的精细化比较策略
- 新的头部子节点,旧的头部子节点
- 新的尾部子节点,旧的尾部子节点
- 新的尾部子节点,旧的头部子节点
- 新的头部子节点,旧的尾部子节点
如果条件1满足,新旧节点头部指针往后移。
如果条件2满足,新旧节点尾部指针往前移。判断是否新的子节点先循环完(头尾位置指针判断),是:就是删除了节点,否:新增了节点,新增的节点按照条件4添加
如果条件3满足,需要移动新的头部子节点到旧的尾部子节点后面
如果条件4满足,需要移动新的头部子节点到旧的头部子节点前面
如果4种都未匹配到,并且指针条件未满足,需要loop匹配
vue在把被移动的节点和匹配的节点设置为undefined
2.react的diff算法
从左往右依次对比,利用元素的index和标识lastIndex进行比较,如果满足index < lastIndex就移动元素,删除和添加则各自按照规则调整
跨层不比较,同层比较,跟vue一样
diff策略
新节点的位置是lastIndex,旧节点的位置是index。从新的节点中依次读取节点索引,对比旧的节点数据索引
- 不满足 index < lastIndex 的条件,不移动;满足 index < lastIndex 的条件,移动节点。
- 每一次比较都需要重新设置 lastIndex=(index,lastIndex)中的较大数
- 移动的节点在前一个被操作的节点后面
- 如果从新的节点集合获取的节点在旧节点集合未找到,就是新增,lastIndex为上一次的值不变
- 如果新的节点集合遍历完了,旧节点还有值就是删除,loop删除掉就行
最恶心的情况:如果把最后一个元素移到最前面,react会依次移动节点向后
3.对比
相似的地方:vue和react的diff算法,都是不进行跨层级比较,只做同级比较。
不同点:
- vue会在patch函数中给被操作的节点打补丁(undefined),在diff的时候更清晰
- vue对比节点,当节点元素类型相同,但是className不同时,认为是不同类型的元素,删除重新创建;而react则认为是同类型节点,进行修改操作
- diff策略,vue的性能优于react
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。