React设计理念
React 是用 JavaScript 构建快速响应的大型 Web 应用程序的首选方式。
是什么制约了应用的快速响应
-
CUP瓶颈
操作大量运输时,导致页面卡顿和掉帧率。 浏览器刷新频率是60HZ/s,也就是1s种渲染60帧,16.6ms渲染一帧,在这段时间内,需要做的事情是js执行,然后布局,再绘制。如果js运行时间过长,超过16.6ms,那就没有时间进行布局和绘制了。所以产生掉帧,页面有动画的时候就会比较明显。
-
IO瓶颈
发送网络请求时,由于要等待请求结果页面才能响应, 因此这个问题是天然存在的。
React做了哪些努力去解决这两个问题
-
CPU瓶颈问题
采用了时间切片的方式,在一帧中预留部分时间给js线程执行任务,这部分时间执行完后,js还没执行完也会讲控制权还给浏览器(将JS同步更新变更为可中断的异步更新),执行GUI线程,让页面进行布局和绘制,不让页面卡顿掉帧。 React中是进行了架构升级,从15的stack Reconciler, 升级为16的fiber Reconciler, 同时增加了调度器。
-
IO瓶颈问题
React给出的答案是:将人机交互研究的结果整合到真实的 UI 中。 React中的实现是引入Suspense。
React新老架构对比
老架构 15
老架构分为2层:
- Reconciler(协调器) 负责找出需要变化的组件并标记
- Renderer(渲染器) 负责将变化的组件渲染出来
Reconciler协调器
当代码中有setState、forceUpdate、ReactDom.render等api执行触发更新时,reconciler执行流程。
- 调用组件的render方法,将JSX转为虚拟Dom,(JSX -> React.createElement -> VNode)
- 找出本次虚拟DOM和上次虚拟DOM变化的部分 (diff算法)
- 交由Renderer将变化的部分渲染
Renderer渲染器
React是跨平台的,不同平台有不同的渲染器, 前端使用的是ReactDom.render.比如还有
- ReactNative渲染器 APP原生组件
- ReactTest渲染器 纯js组件用来测试
- ReactArt 渲染器 渲染成Canvas\SVG
老架构的缺点
老架构的协调器采用的是递归的方法去做diff,这样使得开始后js线程就会一直被占用,不能中断,js执行时间过长就会出现掉帧卡顿, 就是CPU瓶颈。还有React15架构是协调器和渲染器是交替更新的,找到一个diff,就更新一个, 如果更新中途中断了, 则会出现UI错乱(React15不会出现中断更新情况)。
新架构16
新架构分为三层
- Scheduler(调度器) 调度任务的优先级, 高优先级任务会优先进入协调器recociler.
- Reconciler(协调器) 负责找出需要变化的组件并标记
- Renderer(渲染器) 负责将变化的组件渲染出来
Scheduler调度器
调度器有2个功能, 一是设置任务的优先级, 二是可以中断任务,只在浏览器空闲的时候执行任务(浏览器原生requestIdelCallback, 有兼容性, 自己实现了)
Reconciler协调器
与15的协调器相比区别
- 由递归,变为可中断的循环过程。
function workLoopConcurrent() {
// workInProgress 待处理的节点
// shouldYield 浏览器是否还有空余时间
while (workInProgress !== null && !shouldYield()) {
workInProgress = performUnitOfWork(workInProgress);
}
}
- 不再是与renderer交替工作,而是先完成所有diff, 在dom上打上标记, 然后统一交给renderer(渲染器)
Reconciler中引入了一个新的数据结构Fiber, 一个节点对应一个VDOM也对应一个Fiber节点。Fiber节点的引入更加方便的实现了可中断更新。 (理论上VDOM也是可以的, 只是处理上会更复杂)。
Renderer渲染器
Reconciler处理后,就得到了标记过的Fiber树, 根据这些标记,做统一的渲染操作。
学习文档: react.iamkasong.com/