react diff

2017-12-12  本文已影响46人  麦子_FE

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的情况

不使用key的话,react对新老集合对比,发现新集合中B不等于老集合中的A,于是删除了A,创建了B,依此类推直到删除了老集合中的D,创建了C于新集合。= 

酱紫会产生渲染性能瓶颈,于是react允许添加key进行区分

使用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,减少不必要的重渲染。

上一篇下一篇

猜你喜欢

热点阅读