React批处理原理及性能优化实践

事件循环

JavaScript是一门单线程语言,但是会分为同步和异步,同步任务和异步任务分别进入不同的执行"场所"。

同步任务进入主线程,异步任务进入Event Table并注册回调函数,Event Table会将这个函数移入任务队列(task queue),等待主线程的任务执行完毕。当执行栈中的代码执行完毕,执行栈(call stack)中的任务为空时,就会读取任务队列(task queue)中的任务,去执行对应的回调。如此循环,就形成js的事件循环机制(Event Loop)。

事件循环队列里有两种任务,宏任务(同步代码、setTimeout)、微任务(promise),一次事件循环中的同步代码执行完毕后,会去把队列中已有的微任务执行清空,然后进入下一次事件循环

先做几个题感受一下

React批处理原理及性能优化实践_第1张图片

答案:13642


React批处理原理及性能优化实践_第2张图片

答案:136542


React批处理原理及性能优化实践_第3张图片

答案:135642


React批处理原理及性能优化实践_第4张图片

答案:3


React批处理原理及性能优化实践_第5张图片

答案:23

几个问题

setState到底是异步还是同步的?

熟悉react的小伙伴都知道,react是通过状态变化,然后自动计算,将这些变化渲染在界面上的。 但在实际使用过程中,有很多地方表现的与我们预期的不一致。我们来看下一个简单的demo。多个顺序执行的setState不是同步的一个个执行的,会一个个加入队列中,最后一期执行,即批处理『我不会爬到山峰三次,每一次都去更新一个状态』

React 会把我们更新 state 的函数加入到一个队列里面,然后,按照函数的顺序依次调用。同时,为每个函数传入 state 的前一个状态,这样,就能更合理的来更新我们的 state 了。

为什么直接修改this.state无效

要知道setState本质是通过一个队列机制实现state更新的。 执行setState时,会将需要更新的state合并后放入状态队列,而不会立刻更新state,队列机制可以批量更新state。 如果不通过setState而直接修改this.state,那么这个state不会放入状态队列中,下次调用setState时对状态队列进行合并时,会忽略之前直接被修改的state,这样我们就无法合并了,而且实际也没有把你想要的state更新上去。

React17的渲染流程源码解析(事件响应)

React批处理原理及性能优化实践_第6张图片

onPress之后进入到React的事件代理和分发;重点关注一下batchedUpdates。

React的渲染流程源码解析(batchedUpdate)

React批处理原理及性能优化实践_第7张图片

executionContext代表当前处于什么处理流程状态

BatchedContext是批处理状态

React的渲染流程源码解析(setState)

React批处理原理及性能优化实践_第8张图片

this.setState进入的关键代码片段

lane: 获取当前更新的类型(优先级)

保存状态的更新数据

进入调度方法看是否需要将更新应用到渲染

React的渲染流程源码解析(lane)

React批处理原理及性能优化实践_第9张图片

fiber.mde: 当前React的虚拟dom的调度渲染模式

BlockingMode: 含有并发模式小部分功能的模式 ConcurrentMode:并发模式(React18的默认模式)

Reat17中不特意开启,就不会进入上述两个模式中

React的渲染流程源码解析(scheduleUpdateOnFiber 调度)

React批处理原理及性能优化实践_第10张图片

lane: 当前这个更新的类型(优先级)

若当前更新不在批处理状态中

此方法约等于 直接渲染

React17默认模式的批处理是半自动的

事件处理函数、生命周期函数中的同步代码包裹在batchedUpdates的回调中,react框架就能知道所有的同步更新可以合并,到同步代码运行的最后前再做渲染。

如果放在异步代码里,框架内部的事件循环就结束了,无法控制后续异步回调里的更新做批处理,每次更新都会触发渲染。

那有没有全自动?

React18以及React17的并发模式的批处理是全自动的

Why?

对每一个更新操作定义优先级,在一段时间内优先级相同的更新只渲染一次

相关优化思路

  • 先级高的异步任务先处理,优先级低的异步任务等渲染完成再处理;* 方法内的setState、dispatch放入batch回调中处理,batch可以通过train_rn_common引入* * *

今天分享了公司React业务代码中在处理电商场景(日活2千万)一些性能优化操作,没有使用代码块,而是直接截图了 公司业务代码(隐藏了baseUrl),防止一些啥都不懂的前端小朋友误会~

你可能感兴趣的:(react.js,javascript,前端)