合成事件
在 React 自己的生命周期事件和合成事件中,可以拿到 isBatchingUpdates 的控制权,将状态放进队列,控制执行节奏。而在外部的原生事件中,并没有外层的封装与拦截,无法更新 isBatchingUpdates 的状态为 true。这就造成 isBatchingUpdates 的状态只会为 false,且立即执行。所以在 addEventListener 、setTimeout、setInterval 这些原生事件中都会同步更新。

- React 给 document 挂上事件监听
- DOM 事件触发后冒泡到 document
- React 找到对应的组件,造出一个合成事件出来
- 并按组件树模拟一遍事件冒泡
React 17后事件委托挂载到 DOM 容器上,即 ReactDom.Render 所调用的节点上
异步的动机和原理
为什么要出现异步?
从生命周期的角度出发,避免频繁的 re-render(重渲染)
setState 工作流

ReactComponent.prototype.setState = function (partialState, callback) {// 将setState事务放进队列中this.updater.enqueueSetState(this, partialState);if (callback) {this.updater.enqueueCallback(this, callback, 'setState');}};enqueueSetState: function (publicInstance, partialState) {// 根据 this 拿到对应的组件实例var internalInstance = getInternalInstanceReadyForUpdate(publicInstance, 'setState');// 这个 queue 对应的就是一个组件实例的将要更新的 state 数组var queue = internalInstance._pendingStateQueue || (internalInstance._pendingStateQueue = []);queue.push(partialState);// enqueueUpdate 用来处理当前的组件实例enqueueUpdate(internalInstance);}function enqueueUpdate(component) {ensureInjected();// 注意这一句是问题的关键,isBatchingUpdates标识着当前是否处于批量创建/更新组件的阶段if (!batchingStrategy.isBatchingUpdates) {// 若当前没有处于批量创建/更新组件的阶段,则立即更新组件batchingStrategy.batchedUpdates(enqueueUpdate, component);return;}// 否则,先把组件塞入 dirtyComponents 队列里,让它“再等等”dirtyComponents.push(component);if (component._updateBatchNumber == null) {component._updateBatchNumber = updateBatchNumber + 1;}}
