event中注意事项
1 )概述
- 前面把 react 当中事件从开始注入到事件的监听
- 到把整个事件对象给它构造出来,最后去触发这个事件的整体的流程
- 还有一些重要的内容,补充下
- batchedUpdates
- 通过事件去触发的,大部分 setState 都处于 batchedUpdates 里面
- 也就是这一部分的 setState,它们的更新都会一起被提交,最终再一起回调
- 就是之前的举例,调用了 setState 之后,对 state 进行 console.log
- 发现这个 state 没有立即变化,这种情况在事件当中是什么时候被设置的?
- controlled inputs 如何回调
- 关于事件绑定dispatchEvent
- batchedUpdates
2 )源码
2.1 batchedUpdates
定位到 packages/react-dom/src/client/ReactDOM.js#L456
// 依赖注入
ReactGenericBatching.setBatchingImplementation(
DOMRenderer.batchedUpdates,
DOMRenderer.interactiveUpdates,
DOMRenderer.flushInteractiveUpdates,
);
// packages/events/ReactGenericBatching.js#L63
export function setBatchingImplementation(
batchedUpdatesImpl,
interactiveUpdatesImpl,
flushInteractiveUpdatesImpl,
) {
_batchedUpdatesImpl = batchedUpdatesImpl;
_interactiveUpdatesImpl = interactiveUpdatesImpl;
_flushInteractiveUpdatesImpl = flushInteractiveUpdatesImpl;
}
定位上述三个方法
// packages/react-reconciler/src/ReactFiberScheduler.js#L2440
function batchedUpdates<A, R>(fn: (a: A) => R, a: A): R {
const previousIsBatchingUpdates = isBatchingUpdates;
isBatchingUpdates = true;
try {
return fn(a);
} finally {
isBatchingUpdates = previousIsBatchingUpdates;
if (!isBatchingUpdates && !isRendering) {
performSyncWork();
}
}
}
// packages/react-reconciler/src/ReactFiberScheduler.js#L2485
function interactiveUpdates<A, B, R>(fn: (A, B) => R, a: A, b: B): R {
if (isBatchingInteractiveUpdates) {
return fn(a, b);
}
// If there are any pending interactive updates, synchronously flush them.
// This needs to happen before we read any handlers, because the effect of
// the previous event may influence which handlers are called during
// this event.
if (
!isBatchingUpdates &&
!isRendering &&
lowestPriorityPendingInteractiveExpirationTime !== NoWork
) {
// Synchronously flush pending interactive updates.
performWork(lowestPriorityPendingInteractiveExpirationTime, false);
lowestPriorityPendingInteractiveExpirationTime = NoWork;
}
const previousIsBatchingInteractiveUpdates = isBatchingInteractiveUpdates;
const previousIsBatchingUpdates = isBatchingUpdates;
// 在开始执 fn(a, b) 之前设置 下面两个变量为 true
// 设置这两个全局变量,不会立马就去执行后续的 performWork 操作
isBatchingInteractiveUpdates = true;
isBatchingUpdates = true;
try {
return fn(a, b);
} finally {
isBatchingInteractiveUpdates = previousIsBatchingInteractiveUpdates;
isBatchingUpdates = previousIsBatchingUpdates;
if (!isBatchingUpdates && !isRendering) {
performSyncWork();
}
}
}
// packages/react-reconciler/src/ReactFiberScheduler.js#L2517
function flushInteractiveUpdates() {
if (
!isRendering &&
lowestP