1.React Hooks 底层原理
React Hooks 的底层原理是基于 React Fiber 架构的实现。下面是对 React Hooks 底层原理的深度解析:
-
Fiber 架构 : React Fiber 是 React 的新的协调引擎,它的设计目标是支持增量式更新 、优先级调度 、暂停和继续执行等特性。Fiber 架构重新实现了 React 的调度算法,使得 React 可以更灵活地控制组件的渲染过程。
我们都知道react框架的核心算法是diff算法的,其实 diff 算法的核心就是复用节点,通过一一对比也好,通过 map 查找也好,都是为了找到可复用的节点,移动过来。然后剩下的该删删该增增。在 16 之后,为了优化性能,会先把 vdom 转换成 fiber,也就是从树转换成链表,然后再渲染。整体渲染流程分成了两个阶段:
render 阶段 :从 vdom 转换成 fiber,并且对需要 dom 操作的节点打上 effectTag 的标记 commit 阶段:对有 effectTag 标记的 fiber 节点进行 dom 操作,并执行所有的 effect 副作用函数。
从 vdom 转成 fiber 的过程叫做 reconcile(调和),这个过程是可以打断的,由 scheduler 调度执行。第一次渲染不需要 diff,直接 vdom 转 fiber。再次渲染的时候,会产生新的 vdom,这时候要和之前的 fiber 做下对比,决定怎么产生新的 fiber,对可复用的节点打上修改的标记,剩余的旧节点打上删除标记,新节点打上新增标记。
-
Hooks 的调度和状态管理 : React Hooks 的核心思想是在函数组件中引入状态和副作用的管理。Hooks 的使用不依赖于 class 组件,它们是通过调用 React 内部的底层 API 来实现的。Hooks 在函数组件中引入了
useState
、useEffect
、useReducer
等钩子函数,这些钩子函数允许在函数组件中使用状态和副作用。 -
Hooks 实现原理: Hooks 的实现基于 React Fiber 的调度机制和组件树的遍历。当函数组件被调用时,React 会创建一个 Fiber 节点来表示该组件,并将其添加到 Fiber 树中。Hooks 的状态管理和副作用逻辑被存储在 Fiber 节点中,并在组件的每次渲染中被调用。
-
Hooks 的规则: React Hooks 有一些规则和约束,这些规则保证了 Hooks 的正确使用和执行顺序:
- Hooks 只能在函数组件的顶层使用,不能在循环、条件语句或嵌套函数中使用。
- Hooks 的调用顺序必须保持一致,不能在条件语句中或循环中调用 Hooks。
- Hooks 的调用不能出现在任何 JavaScript 函数中,而是在 React 函数组件中调用。
-
Hooks 的优势:
- 使函数组件具备了状态和副作用管理的能力,不再依赖于类组件。
- 更容易共享状态逻辑,实现逻辑的复用。
- 使得 React 组件更加简洁和易于理解。
总的来说,React Hooks 的底层原理是基于 Fiber 架构的调度机制和组件树的遍历实现的。Hooks 通过调用 React 内部的底层 API 来实现状态和副作用的管理,并通过一系列规则保证了 Hooks 的正确使用。Hooks 的出现使得函数组件具备了类组件的功能,使得 React 的组件编写更加灵活和高效。
2.接下来接着谈谈 Fiber 架构
React Fiber 是一种基于协程的实现,用于实现异步渲染和任务优先级调度。这里我们讲一下协程的概念:协程是一种控制流程让出机制,配合线程实现并发能力。
Fiber 架构的核心目标是实现增量渲染和优先级调度,每个 Fiber 可以被看作是一个执行单元,表示了组件树中的一个小部分,负责管理自身对应的组件和其渲染过程。
通过引入协程的概念,React Fiber 实现了任务的切片和中断与恢复,使得 React 能够更高效地处理渲染任务和异步任务,使得 React 应用在处理大量元素或者复杂交互时能够更好地响应用户操作,并避免阻塞主线程,从而提高应用的性能和用户体验。
以下是 React Fiber 架构的主要特点和实现原理:
-
增量渲染: Fiber 架构将渲染过程划分为多个小任务(Fiber),并使用协作式调度的方式执行这些任务。它允许 React 在执行任务的过程中中断和恢复,从而使得页面的渲染过程成为可中断的,可以在多个帧中完成,提高了用户界面的响应速度。
-
优先级调度: Fiber 架构引入了任务优先级的概念,不同任务可以具有不同的优先级,React 可以根据优先级来决定哪些任务应该优先执行,从而确保页面的交互和动画在高优先级任务的影响下得到及时更新,而低优先级任务则可以在后台或空闲时执行,以保证用户体验的流畅性。
-
可中断性和恢复性: Fiber 架构使得渲染过程中的任务可以被中断,并在稍后恢复执行。这种可中断性和恢复性使得 React 应用可以更好地响应用户操作和浏览器的优先级调度,避免了长时间的任务阻塞主线程,提高了应用的性能和流畅度。
-
双缓存渲染: Fiber 架构采用了双缓存渲染技术,即同时维护两棵虚拟 DOM 树,一棵用于渲染当前页面,另一棵用于在后台进行更新。当更新完成后,React 会切换到新的虚拟 DOM 树,从而避免了页面渲染过程中的闪烁和不一致性。
-
增加任务调度器: Fiber 架构引入了任务调度器(Scheduler),负责协调和调度任务的执行顺序和优先级。任务调度器会根据任务的优先级来决定何时执行任务,并允许任务之间相互中断和恢复执行。
3.fiber是怎么实现任务的切片和中断与恢复?
利用sheduler实现任务调度的优先级划分处理,同时看看浏览器的剩余任务处理时间是否有空闲,有时间就处理,没有时间就暂停等待下一轮时间的分配。具体来说,Fiber的任务切片、中断和恢复的过程如下:
任务切片:当React开始执行一个任务(比如渲染组件树)时,它会将任务分割成多个小的执行单元,即fiber。这些fiber表示组件树中的每个组件,每个fiber包含了组件的状态、props、子fiber等信息。
中断:在执行每个fiber时,React会检查是否需要中断当前的任务。中断的条件包括时间片过期、有更高优先级的任务等。如果需要中断,React会将当前的fiber标记为中断状态,并将控制权交还给调度器。
恢复:当下一次调度发生时,调度器会根据优先级选择合适的fiber继续执行。React会从中断的位置恢复执行,继续处理剩下的fiber。这样就实现了任务的中断和恢复。
以下是一个简单的示例代码,展示了Fiber如何实现任务切片、中断和恢复:
javascript
function render() {
// 执行根fiber的渲染任务
performUnitOfWork(rootFiber);
}
function performUnitOfWork(fiber) {
// 执行当前fiber的任务
// ...
if (有更高优先级任务) {
// 中断当前任务,将控制权交还给调度器
scheduleInterrupt(fiber);
return;
}
if (还有子fiber) {
// 执行子fiber的任务
performUnitOfWork(childFiber);
}
// 没有子fiber,向上遍历兄弟fiber
while (无兄弟fiber && 有父fiber) {
// 返回父fiber,继续执行父fiber的任务
fiber = fiber.parent;
}
if (有兄弟fiber) {
// 执行兄弟fiber的任务
performUnitOfWork(siblingFiber);
} else {
// 所有fiber任务都完成,提交更新
commitRoot();
}
}
function scheduleInterrupt(fiber) {
// 将fiber标记为中断状态
fiber.interrupted = true;
// 将fiber加入调度队列,等待下一次调度
scheduleWork();
}
function scheduleWork() {
// 根据优先级选择合适的fiber继续执行
// ...
}
function commitRoot() {
// 提交更新到DOM
// ...
}
function handleClick() {
// 中断当前任务,响应用户点击事件
scheduleInterrupt(currentFiber);
// ...
}
在上面的代码中,render()函数触发了根fiber的渲染任务,然后调用performUnitOfWork()
函数开始执行任务。在执行每个fiber的任务时,会检查是否有更高优先级的任务,如果有,则中断当前任务,将控制权交还给调度器。调度器会根据优先级选择合适的fiber继续执行。
当中断发生时,可以通过用户交互等方式触发,比如handleClick()
函数中的用户点击事件。在中断时,调用scheduleInterrupt()
函数将当前fiber标记为中断状态,并将其加入调度队列,等待下一次调度。
在下一次调度发生时,调度器会根据优先级选择合适的fiber继续执行,从中断的位置恢复执行。这样就实现了任务的中断和恢复。
注意:上述代码只是简化的示例,实际的Fiber实现更加复杂和庞大。以上代码仅用于说明Fiber中任务切片、中断和恢复的基本原理,具体实现还包括对优先级的处理、任务调度策略的设计等。
最后但也是全文最重要的,码字不易,你的鼓励是我持之以恒创作的动力,欢迎点赞关注加搜藏!!!!感谢感谢感谢。