# 结构脉络梳理
# react理念
react理念
我们认为,React 是用 JavaScript 构建快速响应的大型 Web 应用程序的首选方式。 它在 Facebook 和 Instagram 上表现优秀。
我们日常使用App,浏览网页时,有两类场景会制约快速响应:
当遇到大计算量的操作或者设备性能不足使页面掉帧,导致卡顿。
发送网络请求后,由于需要等待数据返回才能进一步操作导致不能快速响应。
这两类场景可以概括为:
1、CPU的瓶颈
时间分片:将同步更新变成可中断的异步更新
一帧的动画是16.6ms, 我们只占用5ms,剩余时间执行样式布局和样式绘制。
2、IO的瓶颈
ios 设置-通用 - 对比 - 设置-siri与搜索
减少网络延迟:将人机交互的研究结果整合到真实的UI中。苹果设置
提前加载suspense/useDeferredValue
function App() {
const [text, setText] = useState("hello");
const deferredText = useDeferredValue(text, { timeoutMs: 2000 });
return (
<div className="App">
{/* 保持将当前文本传递给 input */}
<input value={text} onChange={handleChange} />
...
{/* 但在必要时可以将列表“延后” */}
<MySlowList text={deferredText} />
</div>
);
}
# 新老架构对比
# 15
Reconciler - 协调器 负责找到变化的组件
每当有更新发生时:
- 调用函数组件、class组件中的render方法,将返回的jsx转换为虚拟的DOM
- 将虚拟的DOM和上次更新后的DOM做对比
- 通过对比找到本次需要更新变化的虚拟DOM
- 通知Renderer将变化的虚拟DOM渲染到页面上。
Render - 渲染器 负责将变化的组件渲染到页面上来
- 浏览环境渲染 - ReactDom
- 渲染App原生组件 - ReactNative
- 渲染到Canvas,Svg - reactArt (opens new window)
# 15的缺陷
mountComponent/updateComponent 都会递归更新子组件。 由于递归执行,所以一旦开始,中途就无法中断。当层级很深时,递归更新时间超过了16ms,用户交互就会很卡。
页面由123,变为246,模拟中断,出现了223的情况。看到了更新不完全的DOM。
说明Reconciler和Renderer是交替执行的。
# 16版本
Secheduler - 调度器 调度任务优先级,高优任务优先进入Reconciler
我们以浏览器是否有剩余时间作为任务中断的标准,那么我们需要一种机制,当浏览器有剩余时间时通知我们。
requestIdleCallback (opens new window) 因为这个有兼容性,所以react重写了他,实现了功能更完备的requestIdleCallback的polyfill,这就是 Scheduler (opens new window) 是独立于react的库。
新的-Reconciler - 协调器 负责找到变化的组件
更新工作从递归变成了可以中断的循环过程。每次循环都会调用shouldYield判断当前是否有剩余时间。
/** @noinline */
function workLoopConcurrent() {
// Perform work until Scheduler asks us to yield
while (workInProgress !== null && !shouldYield()) {
workInProgress = performUnitOfWork(workInProgress);
}
}
在React16中,Reconciler与Renderer不再是交替工作。 当Scheduler将任务交给Reconciler后, Reconciler会为变化的虚拟DOM打上代表增/删/更新的标记,类似这样:
export const Placement = /* */ 0b0000000000010;
export const Update = /* */ 0b0000000000100;
export const PlacementAndUpdate = /* */ 0b0000000000110;
export const Deletion = /* */ 0b0000000001000;
整个Scheduler与Reconciler的工作都在内存中进行。 只有当所有组件都完成Reconciler的工作,才会统一交给Renderer。
Render - 渲染器 - 负责将变化的组件渲染到页面上来 Renderer根据Reconciler为虚拟DOM打的标记,同步执行对应的DOM操作。