React 协调算法的一个子流程的理解

91 阅读2分钟

事情的起因是这样的,有个同事写出了类似一下这样的写法:

image.png

长话短说:只要flag不是高频变化的,那这么写大部分情况是没问题的,不会触发后面节点的重新生成问题。


我当时看到后灵光一闪,想到之前看到React的旧文档中有一段说是新增节点最好不要往头部新增,可能会有性能问题:

image.png

文档链接在这里 zh-hans.legacy.reactjs.org/docs/reconc…

于是想当然的认为上面的写法触犯了这个天条,便信誓旦旦的说这不行,会有性能问题,应该往后面加,这样React不会重建后面的所有元素。

但同事是个比较较真的人,他回去怎么调试怎么打印都没发现Comp2有重建的迹象,无论是在dom上勾选了各种断点:

image.png

还是直接保存变化前后的dom引用做对比:

image.png

结果都是完全相等!

遭到质疑的我便开始源码调试的旅程。

1. 定位源码位置

感谢DeepSeek \(^o^)/~

github.com/facebook/re…

2. 调试关键位置

按我的理解,如果产生了性能问题,那么就会是从 [Comp2] -> [Comp1, Comp2] 的过程,那么首先它们没有key,React会用下标作为对比依据,那么一定会有一次 Comp2Comp1 的比较,他们的elementType必不相等,会触发重新创建的流程,代码位置:

image.png

下断点,过到newChildren是[Comp1, Comp2]的时候,进入updateElement方法,于是看到了这一幕:

image.png

currentnull,也就是说Comp1是在和null比,那Comp2呢,不就是原来的Comp2吗,那就不可能触发重新构建树的问题吧,这里回过神来,flag && <Comp1 />在flag是false的时候,并不是什么都没留在那里,不还有个false在那里吗,只是没渲染而已~

image.png

结论就是:flag为false的时候渲染的时候是 [false, Comp2], 更新后渲染的是[Comp1, Comp2]Comp2的位置一直是1,不存在重新创建树的问题。


后记:回头想想好像是个很容易理解的事情,但被刚学习时的先入为主的观念影响了,在深入使用后竟然也没发觉一些浅显的误区,还是不够较真啊。

收获还是有的,对React渲染子节点列表、key的作用、协调的算法流程有了更加深刻的理解~