React 18
18 带来的更新
- 并发模式
- 更新 render API
- 自动批处理
- Suspense 支持 SSR
- startTransition
- useTransition
- useDeferredValue
- useId
- 提供给 第三方库的 Hook
JSX
JSX 是 JS 语法的扩展, 可以编写 类 HTML 的代码
提高了代码可读性与开发效率
生命周期
合成事件
React 在内部对事件做了统一的处理
- 合成事件抹平了浏览器兼容性差异
- React 通过顶层监听的形式,通过事件委托的方式来统一管理所有的事件,可以在事件上区分事件优先级
React Hooks
Fiber 架构
Scheduler 调度器
调度任务的优先级,高优任务优先进入 Reconciler
Reconciler 协调器
负责找出变化的组件, 递归处理虚拟 dom,可中断
中断时机:
有其他更高优任务需要先更新
当前帧没有剩余时间
Renderer 渲染器
负责将变化的组件渲染到页面上
Renderer 根据 Reconciler 为虚拟 DOM 打的标记,同步执行对应的 DOM 操作
Fiber 的结构
Javascript
function FiberNode(tag: WorkTag, pendingProps: mixed, key: null | string, mode: TypeOfMode) {
// 作为静态数据结构的属性
this.tag = tag
this.key = key
this.elementType = null
this.type = null
this.stateNode = null
// 用于连接其他Fiber节点形成Fiber树
// 指向父级Fiber节点
this.return = null
// 指向子Fiber节点
this.child = null
// 指向右边第一个兄弟Fiber节点
this.sibling = null
this.index = 0
this.ref = null
// 作为动态的工作单元的属性
this.pendingProps = pendingProps
this.memoizedProps = null
this.updateQueue = null
this.memoizedState = null
this.dependencies = null
this.mode = mode
this.effectTag = NoEffect
this.nextEffect = null
this.firstEffect = null
this.lastEffect = null
// 调度优先级相关
this.lanes = NoLanes
this.childLanes = NoLanes
// 指向该fiber在另一次更新时对应的fiber
this.alternate = null
}
双缓存 Fiber 树
在 React 中最多会同时存在两棵 Fiber 树。当前屏幕上显示内容对应的 Fiber 树称为 current Fiber 树,正在内存中构建的 Fiber 树称为 workInProgress Fiber 树
React 错误捕获
diff 算法
计算出 Virtual DOM 中真正变化的部分,并只针对该部分进行原生 DOM 操作,而非重新渲染整个页面
把树形结构按照层级分解,只比较同级元素
tree diff
两棵树只对同一层级节点进行比较,只要该节点不存在了,那么该节点与其所有子节点会被完全删除,不在进行进一步比较 只需要遍历一次,便完成对整个 DOM 树的比较
component diff
同类型组件,组件 A 转化为了组件 B,如果 virtual DOM 无变化,可以通过 shouldComponentUpdate()方法优化 不同类型的组件,那么 diff 算法会把要改变的组件判断为 dirty component,从而替换整个组件的所有节点
element diff
key 往前移动的节点不进行任何操作,所以当把最后一个节点移动到头部时,性能损耗最大
- 插入: 新的组件不在原来的集合中,而是全新的节点,则对集合进行插入操作
- 删除: 组件已经在集合中,但集合已经更新,此时节点就需要删除
- 移动: 组件已经存在于集合中,并且集合更新时,组件并没有发生更新,只是位置发生改变(同一层的节点添加唯一 key 进行区分,并且移动,当新集合中位置在旧集合之后时,需要移动)