概述
- React创建的应用程序分两部分,一部分是首次创建的Mount阶段,另一部分是常见的更新更新和事件触发阶段Update阶段。
- 关于DOM更新是两套流程,首次创建和DOM更新。
- 简述React中Class组件生命周期的运行时间点和HOOK组件中UseEffect、UseLayout的运行时间点
Render阶段
- Render阶段又分beginWork阶段和complete阶段
- Render阶段主要的目的是为每一个HTML节点生成Fibre节点,需要执行的事件也会挂载到Fibre节点上, 并根据页面结构生成Fibre链表
Render阶段生成Fibre链表结束后,交给commit阶段。commit阶段会在此基础上执行事件、渲染或更新DOM,最后绘制到页面上。
beginWork阶段——创建Fibre节点
- 在这个阶段会更根据页面的HTML结构和HTML元素生成创建对应的Fibre对象,记录节点的相关信息。如节点类型、节点上的属性、父级对象...
- 在发生页面更新时,React会为每个元素重新构建一个新的Fibre对象。会在此阶段尝试复用上次的Fibre对象,如果没有发生改变就直接复制过来。
会在此阶段调用shouldComponentUpdate生命周期函数,若调用该函数,则react页面在视觉上不会发生更新,但ref的引用还是会发生更新。
complete阶段——创建虚拟DOM
- beginWork生成Fibre对象后,在Complete方法中生成虚拟DOM。如果该Fibre节点有父级对象,则会将创建的虚拟DOM挂载到父级Fibre的属性中
当执行到最后一个节点时,会得到一个虚拟DOM树,然后进入Commit阶段。
Fibre对象和虚拟DOM的构建
Commit阶段
- React相关生命周期
- 处理Render阶段的Fibre链表,执行事件或更新DOM。
commit阶段分3部分,beforeMuation、Mutation、Layout。
beforeMutaion阶段
- 处理focus事件
- 对于Class组件而言,处理getDerivedStateFromProps生命周期函数,可以控制本次更新过程中,页面能不能发生改变。
- 对于HOOK而言,会将useEffect中的回调函数加入一个队列,会在整个Commit阶段完成以后再异步执行,而在本阶段并不会直接执行。
- 调用Class组件的getSnapshotBeforeUpdate生命周期函数
Mutation阶段
- Mutation阶段会遍历包含useEffecTarget属性t的Fibre链表,有需要文本更新的就更新,有需要更新ref的就更新ref。
- 对DOM节点进行增删改查的操作。处理结果会反馈到Fibre节点中(如新增fibre节点,删除fiebr节点),这个Fibre节点并不一定是当前Fibre节点,也可能是当前Fibre节点的父级。
- 对于当前Fibre节点发生更新的情况,若是HOOK组件,会调用useLayoutEffect的销毁函数;对于Class组件而言,会调用componentDidWillUnMount生命周期函数。如果当前Fibre节点类型不是HOOK或Class类型,如div类型、span类型...就不会执行销毁函数的回调。(PS:更新后的结果必须保证上一次的销毁函数调用)
- Mutation阶段的current指针还是之前的,所以执行销毁函数的回调没有问题。
layout阶段
- layout阶段会替换current指针,这就是双缓存机制发生变更的时间点。
- layout阶段会根据current指针是否有值,执行不同的生命周期函数。没有值,执行Class组件的componentDidMount生命周期;有值就执行componentDidUpdate生命周期函数。
- 对于HOOK而言,会调用useEffect的回调函数,将销毁函数加入到队列中。本阶段的最后会检查这个队列,如果有的话会执行队列任务,直到清空后才算完成layout阶段。
- this.setState()的回掉函数,也就是第二个参数,也是在这个阶段执行。
- 会执行useLayoutEffect的回调函数,并将新的销毁函数添加到一个队列中。再次更新时,Mutation阶段就会执行UseLayout的销毁函数。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。