react源码探索之预先知识了解

  • 最近快期末考试,本来不打算写博客的,但是一旦停下不知又是何年,或许是我工作之后,也或许是永远把。毕竟这只是用来记录我大学的殷实生活,大四我不再着重记录,而是投身于找工作。
  • 时光匆匆,重大一开始写博客起,也已经写了八九十篇了,每次回顾以前的博客时,就是感到时间快,真他娘快,转眼三年,看着每一篇博客,想着每一周的经历,感觉不那么真实,好像仿佛回到了那几天,这一切终究是要结束的,天下无不散之宴席
  • 这篇文章是上个月我记的笔记与总结,我之前也阅读过vue源码的大概流程,还有部分api的细节,我明显的对比出react源码的相对复杂,感觉facebook那群团队就是操作系统出身一般。有很多跨领域的技术,比如双缓冲,我之前在写c++游戏时用esayX有过先行了解。总之react确实极其有意思,能学到很多思路。
  • 下面是一些相关名词的介绍,一开始我对这些确实有些困惑的,好在如今网络发达,资源也很多,甚至b栈都有相关的源码讲解,可惜没找到18版本的。不过网上的资源也不能全信,有些人也是一知半解就发出来的,我被错误的引导两天,当时那是越看越懵。

Fiber 架构背景知识

在 React 中,为了实现高效的更新机制,引入了 Fiber 架构。Fiber 是一种数据结构,用于描述 React 组件的工作单元。每个 Fiber 节点对应一个 React 组件实例或者 DOM 元素。

  • 我们提到的虚拟DOM在React中有个正式的称呼------Fiber
    React 在更新过程中,会构建和处理 Fiber 树。这棵树用于跟踪组件的状态、属性以及它们之间的关系等诸多信息。

current和alternate属性的含义

  • 当前屏幕上显示内容对应的Fiber树称为current Fiber树,正在内存中构建的Fiber树称为workInProgress Fiber树
  • current是指向当前正在屏幕上显示的 Fiber 树的引用。它代表了当前用户看到的 UI 对应的组件树结构
  • alternate是与之对应的另一个 Fiber 树的引用。在 React 的更新过程中,React 会构建一个新的 Fiber 树(称为workInProgress树),这个新树的每个节点的alternate属性会指向旧的(current)树中对应的节点。
  • 例如,当一个组件的状态发生改变,React 会开始构建一个新的 Fiber 树来反映这个更新。在构建过程中,新树的节点通过alternate属性与旧树的节点关联起来。这样做的目的是方便在更新完成后,将新树替换旧树(current树),实现高效的 UI 更新。

代码示例帮助理解

  • 假设我们有一个简单的 React 组件:
js 复制代码
import React, { useState } from 'react';
function Counter() {
    const [count, setCount] = useState(0);
    const handleClick = () => {
        setCount(count + 1);
    };
    return (
        <div>
            <p>Count: {count}</p>
            <button onClick={handleClick}>Increment</button>
        </div>
    );
}
  • 在 React 内部,当setCount被调用触发组件更新时,React 会创建一个新的 Fiber 树(workInProgress树)。新树中代表Counter组件的 Fiber 节点的alternate属性会指向旧的(current)树中对应的Counter组件的 Fiber 节点。
  • 这种双缓冲(current和alternate)的机制允许 React 在后台构建新的 UI,同时保持旧的 UI 在屏幕上显示,直到新的 UI 完全构建好并且可以无缝切换,从而避免在更新过程中出现 UI 的闪烁或者不一致等问题。

hostRootFiber

  • hostRootFiber是 React Fiber 树的根节点。在 React 应用中,整个组件树结构是基于 Fiber 架构构建的,而hostRootFiber就是这个树形结构的起点。
  • 它主要用于管理整个应用的渲染过程,包括协调子组件的更新、挂载和卸载等操作。从概念上讲,它类似于传统 DOM 树中的document对象,是整个渲染流程的控制中心。
  • 在 Web 环境中,hostRootFiber与浏览器的 DOM 相关联。它负责将 React 组件树渲染成实际的 DOM 元素。当 React 应用首次加载时,hostRootFiber会创建并挂载初始的 DOM 节点,后续的更新操作也会通过hostRootFiber来更新对应的 DOM 部分。
  • 例如,在一个简单的 React Web 应用中,hostRootFiber会对应 HTML 文件中的
    (假设这是 React 应用挂载的根 DOM 节点)。React 会将整个组件树挂载到这个root节点上,而hostRootFiber就是这个挂载过程的关键节点,它管理着从 React 组件到实际 DOM 元素的转换。

两种重要的数据结构

Fiber

js 复制代码
function FiberNode(
  tag: WorkTag,
  pendingProps: mixed,
  key: null | string,
  mode: TypeOfMode,
) {
  // 作为静态数据结构的属性
  this.tag = tag;
  this.key = key;
  this.elementType = null;// 大部分情况同type,某些情况不同,比如FunctionComponent使用React.memo包裹
  this.type = null;// 对于 FunctionComponent,指函数本身,对于ClassComponent,指class,对于HostComponent,指DOM节点tagName
  this.stateNode = null;// Fiber对应的真实DOM节点

  // 用于连接其他Fiber节点形成Fiber树
  this.return = null;
  this.child = null;
  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;
  // 保存本次更新会造成的DOM操作
  this.effectTag = NoEffect;
  this.nextEffect = null;

  this.firstEffect = null;
  this.lastEffect = null;

  // 调度优先级相关
  this.lanes = NoLanes;
  this.childLanes = NoLanes;

  // 指向该fiber在另一次更新时对应的fiber
  this.alternate = null;
}

这里需要提一下,为什么父级指针叫做return而不是parent或者father呢?因为作为一个工作单元,return指节点执行完completeWork后会返回的下一个节点。子Fiber节点及其兄弟节点完成工作后会返回其父级节点,所以用return指代父级节点

ReactElement

js 复制代码
export type ReactElement = {|
  // 用于辨别ReactElement对象
  $$typeof: any,

  // 内部属性
  type: any, // 表明其种类
  key: any,
  ref: any,
  props: any,

  // ReactFiber 记录创建本对象的Fiber节点, 还未与Fiber树关联之前, 该属性为null
  _owner: any,

  // __DEV__ dev环境下的一些额外信息, 如文件路径, 文件名, 行列信息等
  _store: {validated: boolean, ...},
  _self: React$Element<any>,
  _shadowChildren: any,
  _source: Source,
|};
相关推荐
余生H16 分钟前
前端的Python入门指南(完):错误和异常处理策略及最佳实践
开发语言·前端·javascript·python
你的牧游哥23 分钟前
Mac上使用ln指令创建软链接、硬链接
开发语言·前端·javascript
小兔崽子去哪了34 分钟前
海康摄像头 web 对接
前端·vue.js·html
&活在当下&35 分钟前
Element plus 下拉框组件选中一个选项后显示的是 value 而不是 label
前端·javascript·vue3·element plus
zzy_juheng37 分钟前
弹出框(Dialog)简易使用指南
前端
凌鲨40 分钟前
React Native学习路线图
学习·react native·react.js
Hilaku43 分钟前
手写 Proxy API:从基础到实战
前端
阿征学IT1 小时前
ES6 特性
前端·es6
Mr_Swilder2 小时前
在项目中使用自己发布的包时遇到的一些问题记录
前端
网络安全Max2 小时前
Web 学习笔记 - 网络安全
前端·笔记