Fork me on GitHub

React-源码

React
React-源码

设计理念

快速响应
制约因素

  1. CPU 瓶颈 计算能力
  2. IO 瓶颈 渲染能力

传统解决方案:

  • 节流: 一段时间内将多次操作放到一次执行,滚动
  • 防抖: 在调用停止一段时间之前忽略时间处理程序的调用

架构演进史

老的 React 架构(React 15)
React 15
Reconciler:决定本次更新需要渲染什么组件
reconcile: 协调,Diff 算法,将上次更新的组件与本次更新的组件进行对比,将需要更新的组件渲染到视图中。
Renderer:决定组件渲染到视图中

新的 React 架构(React 16)
React 16
Scheduler:根据优先级调度更新,优先级高的先进入协调器处理,在协调器中进行 diff 算法时,可以被更高优先级的更新中断,等待重新调度。
Scheduler 和 Reconciler 在内存中运行,视图不会发生变化,中断也不会显示错误的页面渲染。

同步更新-异步可中断的更新

Fiber 纤程

代数效应
函数式编程的概念,用于将副作用从函数调用中分离

  • 架构-Fiber 协调器
  • 静态的数据结构
    一个 Fiber 节点对应一个组件,保存了该组件的类型、对应 DOM 等信息,
    就是虚拟 DOM ,JSX
  • 动态的工作单元
    保存组件需要更新的状态和需要更新的副作用。

工作机制:双缓存

  1. 创建应用根节点 FiberRootNode
  2. 调用 render 函数,创建当前应用的根节点 RootFiber,FiberRootNode 的 current 属性指向 RootFiber。首屏渲染前,页面空白,所以 RootFiber 没有子节点。
  3. 首屏渲染
    • 创建新的 RootFiber 树,新旧 RootFiber 通过 current 属性连接
  4. 更新

双缓存工作原理

首屏渲染和更新的区别,创建 workInProgressFiber 树的时候有没有 current 节点(不包括 rootFiber)

JSX 与 Fiber 的关系

JSXReact.createElement的语法糖
参数
type:元素类型,原生 DOM 节点,如div p,在 React 中的 tag 类型是 HostComponent。
props:元素属性<div title='a'></div>
children:元素的子元素
首屏:根据组件返回的 JSX 对象创建 WorkInProgress Fiber 树
更新:根据组件返回的 JSX 对象与组件的 Current Fiber 树对比,生成 WorkInProgress Fiber 树

React Component 与 React Element 的关系

React Element:是React.createElement的调用结果
React Component:类组件或者函数组件
React Component 的名字会作为React.createElement调用的第一个参数 type

render-协调器

创建根 Fiber 节点

beginWork(current, workInProgress)

创建当前 fiber 节点的第一个子 fiber 节点

  • 根据workInProgress.tag执行不同的 update 函数
  • 在 update 函数中,判断当前workInProgress fiber是否包含current fiber,决定是否标记Effect Tags, 执行不同的reconcileChildren(current 不存在不标记副作用),mount 时,只有当前的 rootFiber 节点标记了副作用。
  • reconcileChildren中,根据子节点的类型执行不同的新建FiberNode 操作,即使存在多个子节点还是只新建第一个子节点

completeWork

  • 创建当前节点的 DOM 节点,
  • 赋值给当前 Fiber 节点的stateNode,将当前 DOM 节点的子节点生成的 DOM 树,插入到当前 DOM
  • 为 DOM 节点设置 props 属性,初始化 DOM 事件
  • 创建
-------------本文结束感谢阅读-------------