发生更新的场景:
分为两种:
以上不管是哪一种,都要进行后续步骤:
componentDidMount来源于新子代类组件的挂载
将心产生的节点,对比之前虚拟DOM树中的节点,发现差异,完成更新
react为了提高对比效率,做出以下假设:
层次的移动就是比如原来A组件在第三层第一位,不会突然跑到第二层去
对比的时候,react会直接找到旧树中该节点所在的对应位置进行对比
对比的方式:
名词解释
相同的节点类型: 节点本身类型相同(不管属性,虚拟DOM树更新前后节点都为div则相同,前为div后为p则不相同),如果是react元素则要求type值必须一致
不同的节点类型: 非相同节点类型
key值的作用: 用于通过旧节点,寻找对应的新节点,如果某个旧节点由key值,则其更新时,会在相同层级中找相同的key值进行对比
key值应该在一个范围内(兄弟节点中)唯一,并且应该保持稳定(不要使用随机数之类的)
react依靠假设进行寻找,产生两种情况(找到与未找到)
如果找到了对比目标, 则进行节点类型判断
节点类型一致
根据不同的节点类型做不同的事情
- 空节点: 不做任何事
- DOM节点
1. 直接重用之前的真实DOM对象
2. 对比属性,将变动的属性记录下来,以待将来统一更新(现在不会发生变化)
将来是啥时候? 往上看有个后续步骤,看到真实DOM更新了吗? 那就是将来
3. 遍历该新React元素的子元素,进行递归对比更新
递归对比更新: 说白了就是拿子元素重新走一遍更新流程
- 文本节点
a. 重用之前的真实DOM对象
b. 将新的文本变化记录下来,将来完成更新
- 组件节点: 分为函数组件与类组件
- 函数组件: 重新调用函数,得到一个新的节点对象,进行递归对比更新
- 类组件:
1. 重用之前的实例,
2. 调用生命周期方法 static getDerivedStateFromProps
3. 调用生命周期方法shouldComponentUpdate, 若该方法返回false,则终止
4. 运行render,得到新的节点对象,进行递归对比更新
5. 生命周期函数getSnapshotBeforeUpdate加入执行队列
6. 生命周期函数componentDidUpdate加入执行队列
- 数组节点: 遍历数组, 进行递归对比更新
节点类型不一致
创建新节点 : 进入新节点挂载流程(首次渲染)
卸载旧节点:
1. 文本节点、DOM节点、数组节点、空节点、函数组件节点: 直接放弃该节点,如果节点有子节点,递归卸载节点
2. 类组件节点
- 直接放弃该节点
- 调用该节点的componentWillUnMount函数
- 递归卸载子节点