diff策略
1.web UI中DOM节点跨层级的移动操作特别少,可以忽略不计。
2.拥有相同类型的两个组件将会生成相似的树形结构,拥有不同类型的两个组件将会生成不同树形结构。
3.对于同一层级的一组自节点,他们可以通过唯一id进行区分。
基于以上策略,react分别对一下进行算法优化。
tree diff
react对树的算法进行了分层比较。react 通过 updateDepth对Virtual Dom树进行层级控制,只会对相同颜色框内的节点进行比较,即同一个父节点下的所有自节点。当发现节点不存在,则该节点和其子节点都会被删除。酱紫是需要遍历一次dom树,就完成了整个dom树的对比。

如果是跨层级的移动操作,如图

当根结点发现A消失了,会删除掉A以及他的子节点。当发现D上多了一个A节点,会创建A(包括自己点)节点作为子节点。
所以:当进行跨层级的移动操作,react并不是简单的进行移动,而是进行了删除和创建的操作,会影响到react性能。所以要尽量避免跨层级的操作。(例如:控制display来达到显示和隐藏,而不是真的添加和删除dom)
component diff
1如果是同类型的组件,则直接对比virtual Dom tree
2.如果不是同类型的组件,会直接替换掉组件下的所有子组件
3.如果类型相同,但是可能virtual DOM 没有变化,这种情况下我们可以使用shouldComponentUpdate() 俩判断是否需要进行diff
如图:

如果组件D和组件G,如果类型不同,但是结构类似。这种情况下,因为类型不同,所以react会删除D,创建G。所以我们可以使用shouldComponentUpdate()返回false不进行diff。
所以:component diff 主要是使用shouldComponentUpdate() 来进行优化。
element diff
element diff 涉及三种操作:插入,移动,删除。

不使用key的话,react对新老集合对比,发现新集合中B不等于老集合中的A,于是删除了A,创建了B,依此类推直到删除了老集合中的D,创建了C于新集合。=
酱紫会产生渲染性能瓶颈,于是react允许添加key进行区分。

react首先对新集合进行遍历,for( name in nextChildren),通过唯一key来判断老集合中是否存在相同的节点,如果没有的话创建,如果有的话,if (preChild === nextChild ) 进行移动操作。
移动优化:
在移动前,会将节点在新集合中的位置和在老集合中lastIndex进行比较,如果
if (child._mountIndex < lastIndex) 进行移动操作,否则不进行移动操作。这是一种顺序移动优化。只有在新集合的位置 小于 在老集合中的位置 才进行移动。
如果遍历的过程中,发现在新集合中没有,但是在老集合中的节点,会进行删除操作。
所以:element diff 通过唯一key 进行diff 优化。
总结:
1.react中尽量减少跨层级的操作。
2.可以使用shouldComponentUpdate() 来避免react重复渲染。
3.添加唯一key,减少不必要的重渲染。
网友评论