react18.2.0

在 18 之前,只有在react事件处理函数中,才会自动执行批处理,其它情况会多次更新
在 18,任何情况都会自动执行批处理,多次更新始终合并为一次
hydrate 变为hydrateRoot render改为createRoot().render()
flushSync 退出批量更新,但是内部仍然是批量更新
react17 和 react18的区别就是:从同步不可中断更新变成了异步可中断更新。
useInsertionEffect

在dom生成之后,useLayoutEffect之前,它的工作原理大致合useLayoutEffect相同,只是此时无法访问DOM节点的引用,一般用于提前注入脚本。

fiber架构的理解

15架构采用的是递归 遇到长任务会阻塞 造成用户卡顿
fiber是react现在的链式数组结构  执行异步的调度任务会在宏任务中执行,这样可以保证,不会让用户失去响应
解决的问题
  • 增量渲染。将渲染工作拆分成多个时间片段执行,使得每个时间片段都有机会插入其他优先级更高的任务,保证页面响应性的同时尽可能快地完成渲染工作。
  • 优先级调度。引入了任务优先级的概念,根据任务的紧急程度和重要性对任务进行优先级排序,确保优先级较高的任务能够尽早得到处理,提高用户交互的流畅度。
  • 可中断和恢复。支持任务的中断和恢复,允许在渲染过程中处理更高优先级的任务,以确保更及时地响应用户操作。
  • 更好的错误处理。每个Fiber都有自己的错误边界,可以捕获并处理组件树中发生的错误,并在不崩溃整个应用程序的情况下进行优雅降级。

生命周期

static getDerivedStateFromProps(nextProps,prevState)

shouldComponentUpdate()

render()

componentDidMount()

getSnapshotBeforeUpdate(prevProps,prevState)

componentDidUpdate(prevProps,prevState,snapshot)

componentWillUnmount()

Static getDerivedStateFromError() 更改状态降级组件

componentDidCatch()

7个生命周期 2个静态方法

React事件和原生事件执行顺序

react原生事件

react合成事件

root上挂载事件

react事件是怎么注册的

React 代码执行时,顶层会自动执行事件的注册,初始化事件插件。
React 首次渲染时,会在根节点上绑定所有原生事件。支持冒泡的事件,
React 会同时绑定捕获阶段和冒泡阶段的事件;不支持冒泡的事件,会将事件绑定在具体 DOM 元素上。
事件触发前会从目标元素的 Fiber 节点向上收集同类型事件队列,构造合成对象,同类型的事件会复用同一个合成事件实例对象。
根据监听的事件阶段,决定顺序还是倒序遍历执行事件处理函数(模拟事件的冒泡捕获机制)。

React合成事件的优势:

抹平不同浏览器直接的差异,提供统一的API使用体验
通过事件委托的方式统一绑定和分发事件,有利于提升性能,减少内存消耗

react渲染流程:

Scheduler(调度器)根据优先级lanes区分不同的任务类型,其中同步任务立即同步执行在主线程执行,最快渲染出来
异步任务走Scheduler宏任务里执行的
通过 requestAnimationFrame + 超时时间 + messageChannel 控制那些任务优先进入 Reconciler
 
Reconciler(协调器)负责构建fibertree,找出变化的组件,标记组件的变化
react更新时会从fiberroot从上到下开始遍历,找到变化的节点,最终形成一颗fiberTree叫workInProgressTree
然后将fiberRootNode的current指向workInProgress 完成fiber tree的更新

lifecycle 生命周期阶段
调用生命周期方法

render渲染阶段
React会根据组件的状态变化、props的更新或者⽗组件的重新渲染等触发条件,重新执⾏组件的函数体(函数组件)或者render⽅法(类组件)。
当React执⾏函数组件或render⽅法时,它会检测组件中是否包含了Hooks,如果包含了Hooks,那么React会根据Hooks的顺序依次调⽤它们

commit 阶段
将render阶段生成的更新应用到真实的dom上,完成界面的渲染

useTranstion和useDeferredValue异同:

相同点: useDeferredValue本质上和内部实现与useTranstion一样都是标记成了过度更新任务。

不同点:useTranstion是把startTranstion内部的更新任务变成了过度任务transtion,而useDeferredValue是把原值通过过度任务得到新的值,这个值作为延时状态,一个是处理逻辑,一个是生产一个新的状态。

 

React Diff 会预设几个规则:

  1. 只对同级节点,进行比较
  2. 节点变化,直接删除,然后重建
  3. 存在key值,对比节点的key值

其中单节点Diff相对简单,包含以下流程:

  1. 首先会判断老的Fiber树上有没有对应的Fiber节点,若没有则说明是新增操作,直接在老Fiber树上新增节点并更新DOM
  2. 若老Fiber节点也存在,则判断节点上的key值是否相同,若不同则删除老节点并新增新节点
  3. key值相同,则判断节点的type是否相同,若不同则删除老节点并新增节点
  4. type值也相同,则认为是一个可复用的节点,直接返回老节点就行

多节点的Diff操作主要用于map返回多个相同节点的情况下,可以分为三种情况:新增节点、删除节点以及节点移动,React采用双重遍历的方式来进行三种情况的判断,流程如下:

  1. 第一轮遍历会依次将 children[i] 和 currentFiber 以及 children[i++] 和 currentFiber.sibling 进行对比,当发现节点不可复用时提前结束遍历
  2. 当第一轮遍历无提前结束时,说明所有节点都可以复用,直接返回老节点
  3. 若children遍历完成,currentFiber未完成,则说明是删除操作,需要对未完成的 currentFiber 兄弟节点标记删除
  4. 若children遍历未完成,currentFiber完成,则说明是新增操作,需要生成新的workInProgressFiber节点
  5. 若children和currentFiber都未完成,则说明是节点位置发送了变更,那就对剩余的currentFiber进行遍历,并通过key值找到每一个节点在children中对应的老节点,并将老节点中的位置替换为新节点的


  

 

posted @ 2023-01-13 16:48  国服第一李师师  阅读(102)  评论(0编辑  收藏  举报