浅谈React
前言
- 这篇内容少一些
- 我看的一篇讲diff算法特别好的博客
https://zhuanlan.zhihu.com/p/20346379?refer=purerender
一、React的diff
- 传统diff算法时间复杂度达到了O(n3),React结合所需特点,优化到O(n)
- 策略
- 我们对DOM的跨层级操作很少
- 相同类的两个组件将拥有相似的树形结构
- 同一层一组的组件可以通过key进行区分
- 基于上述策略,react diff的优化分为
tree diff
、component diff
、element diff
- 基于策略一,tree diff只对同一层级的节点进行diff,若节点出现跨层级移动直接新增和删除来处理。
- 基于策略二,React是基于组件来构建应用的,若是同一类组件则继续按原策略进行diff,如果发现组件不为同一类组件则直接替换改组件以及其下所有子节点
- 当节点处于同一层级时,React提供了三种操作:插入、删除和移动,但是仅此的话很可能会造成操作冗余,比如说新的一层节点只是顺序发生了变化,并没有新增或者删除,此时React会一个一个进行对比,如果没有则新增,多余则删除,最后造成简单移动就可以完成却将所有节点都重新删除新增了一次。
- 为此,我们可以为同一层级下一组节点每个节点都添加一个唯一的key。每次先遍历新的虚拟DOM所有节点,然后通过唯一的key判断新旧虚拟DOM是否有相同的key,若有相同的key,则移动组件,同时看相同key的节点属性是否改变,若改变则更新组件属性。
二、小例子解析key
- 假设下图中四个节点代表的是同一层级的同一组节点
- 旧的虚拟DOM中这一层级是
A、B、C、D
,新的虚拟DOM中这一层级是B、E、C、A
- 首先取出新中的第一个节点B,然后我们在老中发现有同样key的B,然后判断是否需要移动
- 然后取出新中的第二个节点E,我们在老中找不到同样的key,则创建节点E,并将位置保持与新中一致
- 然后取出新中第三个节点C,发现有相同的key,然后判断是否需要移动
- 再取出A同上操作
- 最后再对老进行一次遍历,判断老中是否有新中没有的节点,例如D,就删除该节点。
总结
- key是唯一标识
- 最好不要使用index作为key
- 如果存在输入类DOM,用index作为key可能会产生输入残留的问题