react18.2.0
在 18 之前,只有在react事件处理函数中,才会自动执行批处理,其它情况会多次更新 在 18,任何情况都会自动执行批处理,多次更新始终合并为一次
hydrate 变为hydrateRoot render改为createRoot().render()
flushSync 退出批量更新,但是内部仍然是批量更新
react17 和 react18的区别就是:从同步不可中断更新变成了异步可中断更新。
useInsertionEffect
在dom生成之后,useLayoutEffect之前,它的工作原理大致合useLayoutEffect相同,只是此时无法访问DOM节点的引用,一般用于提前注入脚本。
fiber架构的理解
- 增量渲染。将渲染工作拆分成多个时间片段执行,使得每个时间片段都有机会插入其他优先级更高的任务,保证页面响应性的同时尽可能快地完成渲染工作。
- 优先级调度。引入了任务优先级的概念,根据任务的紧急程度和重要性对任务进行优先级排序,确保优先级较高的任务能够尽早得到处理,提高用户交互的流畅度。
- 可中断和恢复。支持任务的中断和恢复,允许在渲染过程中处理更高优先级的任务,以确保更及时地响应用户操作。
- 更好的错误处理。每个Fiber都有自己的错误边界,可以捕获并处理组件树中发生的错误,并在不崩溃整个应用程序的情况下进行优雅降级。
useEffect 钩子的工作原理涉及到 React 的渲染流程和副作用的调度机制。以下是其工作原理的详细说明:
1、调度副作用:当你在组件内部调用 useEffect 时,你实际上是将一个副作用函数及其依赖项数组排队等待执行。这个函数并不会立即执行。
2、提交阶段(Commit Phase):React 渲染组件并且执行了所有的纯函数组件或类组件的渲染方法后,会进入所谓的提交阶段。在这个阶段,React 将计算出的新视图(新的 DOM 节点)更新到屏幕上。一旦这个更新完成,React 就知道现在可以安全地执行副作用函数了,因为这不会影响到正在屏幕上显示的界面。
3、副作用执行:提交阶段完成后,React 会处理所有排队的副作用。如果组件是首次渲染,所有的副作用都会执行。如果组件是重新渲染,React 会首先对比副作用的依赖项数组:如果依赖项未变,副作用则不会执行;如果依赖项有变化,或者没有提供依赖项数组,副作用会再次执行。
4、清理机制:如果副作用函数返回了一个函数,那么这个函数将被视为清理函数。在执行当前的副作用之前,以及组件卸载前,React 会先调用上一次渲染中的清理函数。这样确保了不会有内存泄漏,同时能撤销上一次副作用导致的改变。
5、延迟副作用:尽管 useEffect 会在渲染之后执行,但它是异步执行的,不会阻塞浏览器更新屏幕。这意味着 React 会等待浏览器完成绘制之后,再执行你的副作用函数,以此来确保副作用处理不会导致用户可见的延迟。
通过这种机制,useEffect 允许开发者以一种优化的方式来处理组件中可能存在的副作用,而不需要关心渲染的具体时机。退出清理功能确保了即使组件被多次快速创建和销毁,应用程序也能保持稳定和性能。
生命周期
static getDerivedStateFromProps(nextProps,prevState)
render()
componentDidMount()
getSnapshotBeforeUpdate(prevProps,prevState)
componentDidUpdate(prevProps,prevState,snapshot)
Static getDerivedStateFromError() 更改状态降级组件
7个生命周期 2个静态方法
React事件和原生事件执行顺序
react原生事件
react合成事件
root上挂载事件
react事件是怎么注册的
React合成事件的优势:
react渲染流程:
useTranstion和useDeferredValue异同:
相同点: useDeferredValue本质上和内部实现与useTranstion一样都是标记成了过度更新任务。
不同点:useTranstion是把startTranstion内部的更新任务变成了过度任务transtion,而useDeferredValue是把原值通过过度任务得到新的值,这个值作为延时状态,一个是处理逻辑,一个是生产一个新的状态。
React Diff 会预设几个规则:
- 只对同级节点,进行比较
- 节点变化,直接删除,然后重建
- 存在key值,对比节点的key值
其中单节点Diff相对简单,包含以下流程:
- 首先会判断老的Fiber树上有没有对应的Fiber节点,若没有则说明是新增操作,直接在老Fiber树上新增节点并更新DOM
- 若老Fiber节点也存在,则判断节点上的
key
值是否相同,若不同则删除老节点并新增新节点 - 若
key
值相同,则判断节点的type
是否相同,若不同则删除老节点并新增节点 - 若
type
值也相同,则认为是一个可复用的节点,直接返回老节点就行
多节点的Diff操作主要用于map返回多个相同节点的情况下,可以分为三种情况:新增节点、删除节点以及节点移动,React采用双重遍历的方式来进行三种情况的判断,流程如下:
- 第一轮遍历会依次将 children[i] 和 currentFiber 以及 children[i++] 和 currentFiber.sibling 进行对比,当发现节点不可复用时提前结束遍历
- 当第一轮遍历无提前结束时,说明所有节点都可以复用,直接返回老节点
- 若children遍历完成,currentFiber未完成,则说明是删除操作,需要对未完成的 currentFiber 兄弟节点标记删除
- 若children遍历未完成,currentFiber完成,则说明是新增操作,需要生成新的workInProgressFiber节点
- 若children和currentFiber都未完成,则说明是节点位置发送了变更,那就对剩余的currentFiber进行遍历,并通过key值找到每一个节点在children中对应的老节点,并将老节点中的位置替换为新节点的