异步调度
问题:由于对于大型的 React 应用,会存在一次更新,递归遍历大量的虚拟 DOM ,造成占用 js 线程,使得浏览器没有时间去做一些动画效果,伴随项目越来越大,项目会越来越卡。
对比Vue:
Vue 有这 template 模版收集依赖的过程,轻松构建响应式,使得在一次更新中,Vue 能够迅速响应,找到需要更新的范围,然后以组件粒度更新组件,渲染视图。
React 中,一次更新 React 无法知道此次更新的波及范围,所以 React 选择从根节点开始 diff ,查找不同,更新这些不同。
解决:
把 React 的更新,交给浏览器自己控制,浏览器先执行绘制任务,空闲时间执行更新任务,解决了卡顿问题。即采用异步调度的方法。
时间分片
React让浏览器控制React更新:浏览器每执行一次事件循环都会:处理事件,执行 js,调用requestAnimation
,布局 Layout,绘制 Paint,在一次执行后,浏览器进入空闲时,可以执行更新任务
谷歌浏览器提供的一个 API, 在浏览器有空余的时间,浏览器就会调用 requestIdleCallback 的回调。
requestIdleCallback(callback,{ timeout })
- callback 回调。浏览器空余时间执行回调函数。
- timeout 超时时间。如果浏览器长时间没有空闲,那么回调就不会执行,为了解决这个问题,可以通过 requestIdleCallback 的第二个参数指定一个超时时间。
React 为了防止 requestIdleCallback
中的任务由于浏览器没有空闲时间而卡死,所以设置了 5 个优先级。
Immediate
-1 需要立刻执行。UserBlocking
250ms 超时时间250ms,一般指的是用户交互。Normal
5000ms 超时时间5s,不需要直观立即变化的任务,比如网络请求。