欢迎光临
我们一直在努力

就让我们从react的渲染逻辑出发吧

首先我们要理解什么是DOM?

要知道这个我们需要知道浏览器的渲染过程:1. 字节流 → 2. 字符流 → 3. 令牌化 → 4. 构建DOM树 → 5. 构建CSSOM树 → 6. 构建渲染树 → 7. 布局 → 8. 绘制 → 9. 合成

其中DOM就是浏览器渲染的基石,DOM 是浏览器根据 HTML 结构解析生成的页面节点树

没有 DOM,浏览器就无法理解页面结构,也无法应用 CSS 样式或执行 JavaScript 交互。

那如何理解react中的虚拟DOM技术?

React 并没有改变浏览器渲染页面的底层逻辑

DOM 来实现页面更新。但真实 DOM 的创建、修改和渲染成本较高,频繁操作会导致页面性能下降。

因此 React 引入了虚拟 DOM 方案:

你写 JSX → 变成 createElement → 生成虚拟 DOM(图纸)

虚拟 DOM 本质上是一个普通 JavaScript 对象,它不是根据浏览器现有页面生成,而是完全根据开发者编写的 React 代码生成。

在 React 渲染流程中:

  • 组件代码会先构建出对应的虚拟 DOM;
  • 当状态或属性更新时,会生成新的虚拟 DOM,并通过 Diff 算法 与旧虚拟 DOM 进行对比;
  • 最终 React 只会将差异部分更新到真实 DOM 上,从而减少直接操作真实 DOM 的次数与性能开销。
  • 而我们在 React 中写的 JSX,本质是创建虚拟 DOM 的语法糖,它让我们可以用类似 HTML 的写法,更直观地描述页面结构,最终会被编译成创建虚拟 DOM 的逻辑。

    那么在react频繁使用的react hooks底层又是个什么东西呢?

    hooks的本质是react在组件外部单独维护一套链表结构,通过闭包让组件获取状态。

    所有的状态和副作用逻辑,都按固定的调用顺序存储在链表中。每次组件重新渲染,React 都会严格按照相同的顺序读取、更新对应状态。因为 Hooks 完全依赖调用顺序来匹配状态,所以不能在 if、for、嵌套函数中使用,否则会导致状态错乱

    特点:

    React 不会让 Hooks 链表 “轮空” 或 “跳过”。第一次渲染时,Hooks 的数量和顺序就固定了链表结构。没有使用 Hooks 的组件,就不会创建链表。一旦使用了 Hooks,结构永久不变,所以必须保证每次渲染顺序一致。

    react中的Fiber是什么,它负责什么内容呢?

    Fiber 是 React 为了解决“页面卡顿”而发明的一种“可以随时暂停和恢复”的智能渲染机制。

    浏览器执行机制是这样的:1 秒钟要刷新 60 次页面 = 16ms 刷新一次(60hz)

    就是把大渲染切成小片段,每段只跑一点点时间到点就暂停,把控制权还给浏览器浏览器忙完,React 再继续渲染保证页面永远不卡死

    就是我们上面说的,它是一种支持可中断、基于优先级的渲染架构(React Reconciler)。

    为了能够“暂停和恢复”,老的“递归树”结构肯定不能用了(因为递归无法记录暂停位置)。
    React 发明了一种全新的链表树结构,这就是 Fiber 节点。
    每个 Fiber 节点不仅有自己是谁的信息,还有 3 个极其关键的指针:

    • child:指向自己的大儿子(第一个子组件)

    • sibling:指向自己的亲兄弟(下一个兄弟组件)

    • return:指向自己的亲爹(父组件)
      有了这三个指针,React 就可以随时从树的任何一个节点跳出,下次回来时,顺着指针就能精准找到上次停下的地方!

    它也作为组件的档案袋,每个组件对应一个Fiber,一个组件渲染时需要的数据(Props、State、DOM 节点信息、要执行的副作用),全都存在这个组件对应的 Fiber 对象上。
    Hooks 的那个单向链表,就是挂载在这个 Fiber 节点的 memoizedState 属性上的

    重要的双缓存:

    既然 Fiber 是走走停停的,那会不会出现页面渲染了一半,上面是新 UI,下面是老 UI 的情况?

    回答: 绝对不会!因为 Fiber 引入了“双缓存机制”(借鉴了游戏引擎的画面渲染原理)。
    内存里其实同时存在两棵 Fiber 树:

  • Current 树:目前屏幕上显示的内容对应的树。

  • WorkInProgress 树(WIP树):正在内存里慢慢构建、走走停停的新树。

  • React 所有的“走走停停”都是在内存里的 WIP 树上操作的。用户根本看不见。
    只有当 WIP 树全部构建完成后,React 会在不到 1 毫秒的时间内,把屏幕的指针从 Current 树瞬间切换到 WIP 树。这就保证了用户看到的页面永远是完整的、不撕裂的!

     Render 阶段和 Commit 阶段的区别

    Render 阶段是在脑海里计算“界面应该变成什么样”,可以被打断;Commit 阶段是把计算结果“真正画到屏幕上”,绝不能被打断

    1. Render 阶段(找不同)

    • 触发时机: 当你调用 setState 或者初次加载时。

    • 具体动作: React 会调用你的函数组件(比如执行 App()),拿到最新的 JSX。然后把它和老的虚拟 DOM 进行对比(这就是著名的 Diff 算法)。

    • 产出物: 它会在内存里构建我们在上一讲提到的 WorkInProgress Fiber 树。并且在这个树的节点上打标签(Flags/EffectTags),比如:这个节点需要“插入(Placement)”,那个节点需要“更新(Update)”,另一个需要“删除(Deletion)”。

    2. Commit 阶段(打补丁)

    • 触发时机: 当整棵 WorkInProgress Fiber 树构建完毕,且所有差异都找出来之后。

    • 具体动作: React 拿着刚才打满标签的树,去操作真正的浏览器 DOM(比如调用 document.createElement 或 appendChild)。

    • 产出物: 用户的屏幕真正发生了变化。并且,React 会在这一步把指针切换,完成双缓存树(Double Buffering)的替换。

    赞(0)
    未经允许不得转载:171主机测评 » 就让我们从react的渲染逻辑出发吧
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址