DOM Diff(差分)算法
1. 算法由来
React调用render()方法后,会生成一个React元素组成的树。
再次调用,生成一个新的树。React比较两者的差异,然后更新UI。
如果单纯使用算法,来查找两个DOM树的差异值,算法复杂度为O(n^3)。
为了提高渲染效率,假定:
1)元素类型不同,是不同的树
2)子元素可以通过key值来判断是否稳定
这样算法复杂度降低到O(n)
2. 算法比较步骤
1. 比较根节点
如果类型不同,卸载整个DOM节点,重新加载;
如果类型相同
1)如果是普通的html标签类型,比较属性,更新变化的属性。
2)如果是组件类型,更新props,引发componentWillReceiveProps和componentDidUpdate方法调用
2. 比较子节点(无key)
如果类型不同,卸载字节点,重新加载;
如果类型相同,依次比较字节点内容
1)这种情况下,追加元素开销最小,因为前面都相同;
2)头部插入元素开销最大;因为比较来看,第一个开始至最后一个都不相同。
<ul> <li>Duke</li> <li>Villanova</li> </ul> <ul> <li>Connecticut</li> <li>Duke</li> <li>Villanova</li> </ul>
3. 比较子节点(有key非index)
对于上面的情况,如果同一列表的所有子元素有一个唯一值key值。
React先比较key值,如果相同的key值存在,但是位置不同,只移动位置。
元素移动位置只能在兄弟之间移动。
<ul> <li key="2015">Duke</li> <li key="2016">Villanova</li> </ul> <ul> <li key="2014">Connecticut</li> <li key="2015">Duke</li> <li key="2016">Villanova</li> </ul>
4. 比较子节点(有key是index)
˙这种情况,如果字节点顺序改变,可能会引起错误。
比如子列表中含有非受控组件input。此时如果触发排序,会导致input的state出现互相篡改。