这一把子彻底搞懂 setState 原理
先回忆一下上一篇:面试官:“宝子,setState 是同步还是异步的呀?”
这上一篇中,我们基本搞清楚了原理流程,那具体的代码是如何实现的呢?
在 setState 的调用中,有一个合成事件起到了关键性的作用。接下来,我们先去搞清楚这个小可爱,再来看具体的 setState 的代码实现。
合成事件
首先明确定义,在 React 中为元素添加的事件被叫做合成事件。
合成事件的好处有两个:
一是屏蔽了浏览器之间关于事件处理的兼容性问题,为合成事件对象内部提供了统一的 API;
二是性能的提升, 事件都被委托给 document 。
React 并不会将事件添加到真正的 DOM 元素身上,它会将所有事件委托给 document 执行。如下图所示:
React 会在拥有事件的 DOM 对象身上添加一个 store 对象,在 store 对象中存储事件名称及事件处理函数,然后通过 document 分发事件。
当事件被触发后,通过获取事件源对象,查看事件源对象中是否存在 store 对象,获取 store 对象中事件处理函数,执行事件处理函数。
合成事件的事件对象在使用完成以后会被销毁。我长得帅,所以,我写了一段模拟性的代码,你看不看就随意了:
代码的注释中说的已经非常清楚了,爱看不看吧,就这样……
setState 实现原理
接着,我们再把上面的图拿出来,我分为了四段,进行了具体的梳理。先看图,再看字,最后上代码 👇
1、当 setState 方法被调用后,方法会将状态传递给组件更新器,让组件更新器将状态临时存储起来。每个组件都会有自己的组件更新器,当需要更新组件时调用组件更新器。
2、状态临时保存完成后判断当前是否为批量更新模式,如果是,将组件更新器添加到更新队列中;如果不是,直接更新组件。
批量更新模式是如何设置的:当触发合成事件时, 在事件处理函数执行之前,会先将批量更新模式设置为 true,然后执行事件处理函数收集状态。当事件处理函数执行完成后,执行批量更新操作,即从更新队列中获取组件更新器并调用。组件更新器调用完成后再将批量更新模式设置为 false。
3、更新组件时,先判断是否有状态需要更新,如果有就先计算最新状态,将得出的最新状态重新设置给组件。
计算状态时,如果状态是函数类型,调用函数传入当前状态,返回最新状态。如果状态是对象类型,使用对象状态覆盖原有状态。
4、组件状态计算完成后,通过调用组件内部的 render 方法获取新的 VirtualDOM,再通过 DOM 对象获取旧的虚拟 DOM,然后调用 diff 方法进行比对,对比完成后将差异更新到真实 DOM 对象中。
下面的代码,就是配合前面的流程图和文字描述实现的具体代码了。我看你也挺聪明的,所以加了非常详细的注释,就是为了遏制你的智力增长,如果还看不懂,那就算了吧,建议你去和娜塔莎抢婚,单身程序员这条路可能不适合你哟 (●'◡'●)。
好了,就到这里吧。没想到你竟然真的没看代码,就知道往下拖进度条,哎,放弃吧,翠花是娜塔莎的,不可以插足!
当然,如果能点赞,我可以考虑送你一只翠花┗|`O′|┛。
推荐阅读:
知乎问题:如何看待 TC39 的提案 Module Fragments?
恭喜你又在前端道路上进步了一点点。
点个“在看”和“赞”吧!