React相关

101 阅读4分钟

一、React架构

(一)栈式架构(Stack)

在React Fiber架构之前使用的是栈式架构,它基于递归的方式进行Virtual DOM的比较和更新,递归遍历一旦开始需要一直执行完所有比较和更新,无法中断或分段处理。且当应用程序中有大量组件和复杂的数据结构时,递归比较和更新依然会消耗大量的计算资源和事件。没有引入优先级的概念,所有任务顺序执行,导致页面在更新过程中出现卡顿现象影响用户的交互体验。

(二)Fiber架构

在React 16.x之后引入了Fiber架构,通过异步渲染和优先级控制来改善大型应用的响应速度和用户体验。

  1. Fiber节点:它是虚拟DOM的实现方式,其本质是一个对象,使用了链表结构,对象之间使用了链表的结构串联。一个Fiber包括child(子)、sibling(同级)、return(上级)等属性。这种结构和递归树相比,最重要的优势是在进行虚拟DOM对比计算时,可以中断和恢复
  2. 调度器Scheduler、协调器Reconciler、渲染器Renderer共同工作来提供React组件的渲染和更新。
  • Scheduler(调度器):根据任务优先级安排任务执行顺序;优先级:Immediate、Normal、Low
  • Reconciler(协调器):根据新旧虚拟DOM的差异确定需要更新的部分;
  • Renderer(渲染器):将更新的虚拟DOM转换为实际UI输出;
  1. 时间切片TimeSlice:引入时间切片的概念,即将大的渲染任务分解为多个较小的片段,每个片段都可以在一帧内完成,这样可以防止长时间的任务阻塞主线程,保证界面流畅。时间切片允许React在每个片段之间执行其他优先级更高的任务。
  2. 双重缓冲Double Buffering:使用两个Fiber树来管理渲染,即当前树(current tree)和工作树(work-in-progress tree)。当前树代表屏幕上当前显示的内容,工作树用于准备下一次渲染更新,实现更平滑的更新。

二、React渲染的两个阶段

react渲染流程分为两个阶段:render阶段和commit阶段。

  1. render阶段:协调器Reconciler根据新旧虚拟DOM树的差异确定需要更新的部分。
  2. commit阶段:render阶段完成后,开启commit阶段,此阶段一旦开始就会同步执行到完成渲染工作,不可被打断。分为三个阶段
  • before mutation:准备工作;
  • mutation:执行dom的增删改操作;
  • layout阶段:执行一些最终的dom结构信息,如元素尺寸位置等。

三、React18的更新

  1. setState的自动批量处理,在react18以前原生js事件、promise、setTimeout、setInterval不会被批量处理,在react18,所有事件都进行批量处理,即多次setState会被合并成1次执行,提高了性能,在数据层,将多个状态更新合并成一次处理。
  2. 引入新的root API,支持并发模式的渲染(new concurrent renderer)
  3. flushSync:批量更新时一个破坏性的更新,如果想退出批量更新,可以使用flushSync
  4. 组件返回值更新:在react17中,返回空组件只能返回null,返回undefined会报错,react18中不再检查undefined而导致的崩溃。
  5. strict mode更新:使用严格模式时,react会对每个组件返回渲染两次,以便观察一些意想不到的结果,在react17中去掉了一次渲染的控制台日志以便阅读,react18中取消了这个限制,第二次会以浅灰色出现在控制台。
  6. Suspense不再需要fallback捕获
  7. 支持userId:在服务器和客户端生成相同的唯一一个id,避免hydrating的不兼容
  8. useSyncExternalStore:用于解决外部数据撕裂问题
  9. useInsertionEffect:这个Hooks只建议css-in-js库来使用。这个Hooks执行时机在DOM生成之后,useLayoutEffect之前,它的工作原理大致与useLayoutEffect相同,此时无法访问DOM节点的引用,一般用于提前注入脚本。
  10. Concurrent Mode(并发模式):不是一个功能而是一个底层设计,
ReactDOM.createRoot(root).render(<App />);

它可以帮助应用保持响应,根据用户的设备性能和网速进行调整,它通过渲染可中断来修复阻塞渲染机制。在并发模式中,react可以同时更新多个状态。区别就是同步不可中断更新变成了异步可中断更新。

四、JSX与JS

JSX是react的语法糖,它允许在html中写js,也可以说是JS的语法扩展,其本质就是React.createElement()。Babel插件实现JSX到JS的编译,主要基于AST的转换。主要分为三个阶段:

  1. 解析:babel首先使用解析器将JSX转化为AST(树状结构),并识别JSX中的标签、属性、子元素等将他们转化为AST中的节点。
  2. 转换:接下来Babel会对AST进行遍历和转换,识别出节点将其转换成对应的React.createElement函数调用。
  3. 生成:Babel会将转换后的AST生成为目标JS代码。