react 部分理解

105 阅读4分钟

React 核心源码分析

调度和协调(reconciler):

React 核心源码中的调度和协调模块负责管理组件的更新和渲染。这包括调度更新的优先级、协调组件树的变更、执行更新的阶段和过程等。其中的关键模块包括:

  • 调度器 (Scheduler):负责安排和调度组件更新的优先级,以实现异步和批量更新。
  • 调度优先级 (Priority):定义了不同更新任务的优先级,如同步任务、异步任务、动画任务等。
  • 调度策略 (Scheduling):确定何时执行更新和如何分配时间片来避免阻塞主线程。
  • 任务调度器 (Task Scheduler):与底层平台(如浏览器)交互,安排和执行任务。

Fiber 架构:

React 核心源码中的 Fiber 架构是实现调度和协调的核心机制。Fiber 是一种数据结构,用于表示组件树的节点,并且在协调过程中记录组件的变更、执行过程和状态。Fiber 架构的关键模块包括:

  • Fiber 节点 (Fiber Node):表示组件树中的一个节点,包含了组件的类型、状态、子节点等信息。

    1)this.return = null //指向父节点。

    为什么是return 指向父节点,而不是parent?

    每一个fiber 都是一个工作节点,作为一个工作节点,在子节点以及兄弟节点完成工作后会返回父节点。

    2)this.sibling = null //指向下一个兄弟节点

    3)this.child = null //指向子节点

  • 工作循环 (Reconciliation):通过遍历和协调 Fiber 节点,处理组件的更新和渲染。

  • Diff 算法 (Reconciliation Algorithm):比较新旧 Fiber 树,找出需要更新的部分,并生成更新指令。

  • 任务调度器 (Scheduler):根据优先级和时间片分配,安排和执行更新任务。

组件和元素:

React 核心源码中的组件和元素模块负责处理组件的定义、创建和渲染。这包括组件的生命周期管理、状态管理、事件处理和渲染输出等。关键模块包括:

  • React 元素 (React Element):用于描述组件树的虚拟节点,包含组件类型、属性和子元素等信息。
  • React 组件 (React Component):组件的基类,定义了组件的生命周期方法、状态管理和事件处理等。
  • 渲染器 (Renderer):根据 React 元素和组件的描述,将组件树渲染为实际的 UI 输出。
  • 协调器 (Reconciler):负责组件的协调和更新,根据组件的变更生成更新指令。

上下文和钩子:

React 核心源码中的上下文和钩子模块提供了上下文传递和组件状态管理的能力。这包括上下文的创建和共享、钩子函数的定义和调用等。关键模块包括:

  • 上下文 (Context):用于在组件树中共享数据,提供了创建上下文和上下文传递的机制。
  • 钩子 (Hooks):提供了在函数组件中管理状态和其他 React 功能的能力,如 useState、useEffect 等。

React Fiber 如何通过双缓存更新DOM?

在内存中绘制当前的fiber dom,绘制完毕后直接替换上一帧的fiber dom,由于省去了两帧替换间的计算时间,不会出现从白屏到出现画面的闪烁情况;在React中最多会同时存在两棵Fiber树。当前屏幕上显示内容对应的Fiber树称为current Fiber,正在内存中构建的Fiber树称为workInProgress Fiber,两者通过alternate连接;React应用的根节点通过current指针指向不同的fiber dom切换,当update时,workInProgressFiber rende完成后会跟currentFiber 替换,下一次更新会将当前currentFiber(上一次的workInProgressFiber)替换

currentFiber.alternate === workInProgressFiber;
workInProgressFiber.alternate === currentFiber;
  • mount
  1. 首次执行ReactDOM.render会创建fiberRootNode(源码中叫fiberRoot)和rootFiber。其中fiberRootNode是整个应用的根节点,rootFiber是所在组件树的根节点;

    1. 区分fiberRootNode与rootFiber:因为在应用中我们可以多次调用ReactDOM.render渲染不同的组件树,他们会拥有不同的rootFiber。但是整个应用的根节点只有一个,那就是fiberRootNode;

    2. fiberRootNode的current会指向当前页面上已渲染内容对应Fiber树,即current Fiber;

    3. 因为是首次渲染,此时页面还没有挂在所有的DOM,所以rootFiber还没有子fiber dom

      image-20240429171938351

  1. render阶段,根据组件返回的JSX在内存中依次创建Fiber节点并连接在一起构建Fiber树,被称为workInProgress Fiber;

    a) 在构建workInProgress Fiber树时会尝试复用current Fiber树中已有的Fiber节点内的属性(后续的diff),在首屏渲染时只有rootFiber存在对应的current fiber(即rootFiber.alternate)

    image-20240429172205545

  1. alternate阶段:此时workInProgress fiber已经构建完成,fiberRootNode的current指向了workInProgress fiber

image-20240429173454549

  • update
  1. 假设p元素更新,这会开启一次新的render阶段并构建一棵新的workInProgress Fiber 树,且会尽可能服用显有的current Fiber

    image-20240429173647011

    1. alternate阶段

workInProgress fiber在更换完后,fiberRootNode的current指针更换·

image-20240429173825813