跳到主要内容

simple event plugin

一、作用

二、提取事件

备注
function extractEvents(
dispatchQueue: DispatchQueue,
domEventName: DOMEventName,
targetInst: null | Fiber,
nativeEvent: AnyNativeEvent,
nativeEventTarget: null | EventTarget,
eventSystemFlags: EventSystemFlags,
targetContainer: EventTarget,
): void {
const reactName = topLevelEventsToReactNames.get(domEventName);
if (reactName === undefined) {
return;
}
let SyntheticEventCtor = SyntheticEvent;
let reactEventType: string = domEventName;
switch (domEventName) {
case 'keypress':
// Firefox creates a keypress event for function keys too. This removes
// the unwanted keypress events. Enter is however both printable and
// non-printable. One would expect Tab to be as well (but it isn't).
// Firefox 对功能键也会创建 keypress 事件。这个可以移除不需要的 keypress 事件。然而,
// Enter 键既是可打印的也是不可打印的。人们可能会认为 Tab 键也是如此(但实际上不是)。
// TODO: Fixed in https://bugzilla.mozilla.org/show_bug.cgi?id=968056. Can
// probably remove.
if (getEventCharCode(nativeEvent as any as KeyboardEvent) === 0) {
return;
}
/* falls through */
/* 穿透 */
case 'keydown':
case 'keyup':
SyntheticEventCtor = SyntheticKeyboardEvent;
break;
case 'focusin':
reactEventType = 'focus';
SyntheticEventCtor = SyntheticFocusEvent;
break;
case 'focusout':
reactEventType = 'blur';
SyntheticEventCtor = SyntheticFocusEvent;
break;
case 'beforeblur':
case 'afterblur':
SyntheticEventCtor = SyntheticFocusEvent;
break;
case 'click':
// Firefox creates a click event on right mouse clicks. This removes the
// unwanted click events.
// Firefox 在右键点击时会创建一个点击事件。这会移除不需要的点击事件。
// TODO: Fixed in https://phabricator.services.mozilla.com/D26793. Can
// probably remove.
if (nativeEvent.button === 2) {
return;
}
/* falls through */
/* 穿透 */
case 'auxclick':
case 'dblclick':
case 'mousedown':
case 'mousemove':
case 'mouseup':
// TODO: Disabled elements should not respond to mouse events
// 待办事项:被禁用的元素不应响应鼠标事件
/* falls through */
/* 穿透 */
case 'mouseout':
case 'mouseover':
case 'contextmenu':
SyntheticEventCtor = SyntheticMouseEvent;
break;
case 'drag':
case 'dragend':
case 'dragenter':
case 'dragexit':
case 'dragleave':
case 'dragover':
case 'dragstart':
case 'drop':
SyntheticEventCtor = SyntheticDragEvent;
break;
case 'touchcancel':
case 'touchend':
case 'touchmove':
case 'touchstart':
SyntheticEventCtor = SyntheticTouchEvent;
break;
case ANIMATION_END:
case ANIMATION_ITERATION:
case ANIMATION_START:
SyntheticEventCtor = SyntheticAnimationEvent;
break;
case TRANSITION_END:
SyntheticEventCtor = SyntheticTransitionEvent;
break;
case 'scroll':
case 'scrollend':
SyntheticEventCtor = SyntheticUIEvent;
break;
case 'wheel':
SyntheticEventCtor = SyntheticWheelEvent;
break;
case 'copy':
case 'cut':
case 'paste':
SyntheticEventCtor = SyntheticClipboardEvent;
break;
case 'gotpointercapture':
case 'lostpointercapture':
case 'pointercancel':
case 'pointerdown':
case 'pointermove':
case 'pointerout':
case 'pointerover':
case 'pointerup':
SyntheticEventCtor = SyntheticPointerEvent;
break;
case 'submit':
SyntheticEventCtor = SyntheticSubmitEvent;
break;
case 'toggle':
case 'beforetoggle':
// MDN claims <details> should not receive ToggleEvent contradicting the
// MDN 声称 <details> 不应该接收 ToggleEvent,这与规范相矛盾:
// spec: https://html.spec.whatwg.org/multipage/indices.html#event-toggle
SyntheticEventCtor = SyntheticToggleEvent;
break;
default:
// Unknown event. This is used by createEventHandle.
// 未知事件。此用于 createEventHandle。
break;
}

const inCapturePhase = (eventSystemFlags & IS_CAPTURE_PHASE) !== 0;
if (
enableCreateEventHandleAPI &&
eventSystemFlags & IS_EVENT_HANDLE_NON_MANAGED_NODE
) {
const listeners = accumulateEventHandleNonManagedNodeListeners(
// TODO: this cast may not make sense for events like
// "focus" where React listens to e.g. "focusin".
// TODO: 对于像 "focus" 这样的事件,这种类型转换可能没有意义,因为 React 会监听例如
// "focusin"。
reactEventType as any as DOMEventName,
targetContainer,
inCapturePhase,
);
if (listeners.length > 0) {
// Intentionally create event lazily.
// 有意延迟创建事件。
const event: ReactSyntheticEvent = new SyntheticEventCtor(
reactName,
reactEventType,
null,
nativeEvent,
nativeEventTarget,
);
dispatchQueue.push({ event, listeners });
}
} else {
// Some events don't bubble in the browser.
// In the past, React has always bubbled them, but this can be surprising.
// We're going to try aligning closer to the browser behavior by not bubbling
// them in React either. We'll start by not bubbling onScroll, and then expand.
// 一些事件在浏览器中不会冒泡。
// 过去,React 总是会冒泡这些事件,但这可能会令人意外。
// 我们将尝试更接近浏览器的行为,在 React 中也不冒泡这些事件。
// 我们将从不冒泡 onScroll 开始,然后逐步扩展。
const accumulateTargetOnly =
!inCapturePhase &&
// TODO: ideally, we'd eventually add all events from
// nonDelegatedEvents list in DOMPluginEventSystem.
// Then we can remove this special list.
// This is a breaking change that can wait until React 18.
// TODO: 理想情况下,我们最终会将 DOMPluginEventSystem 中 nonDelegatedEvents 列表
// 的所有事件都添加进来。
// 然后我们可以移除这个特殊列表。
// 这是一个破坏性更改,可以等到 React 18 再做。
(domEventName === 'scroll' || domEventName === 'scrollend');

const listeners = accumulateSinglePhaseListeners(
targetInst,
reactName,
nativeEvent.type,
inCapturePhase,
accumulateTargetOnly,
nativeEvent,
);
if (listeners.length > 0) {
// Intentionally create event lazily.
// 有意延迟创建事件
const event: ReactSyntheticEvent = new SyntheticEventCtor(
reactName,
reactEventType,
null,
nativeEvent,
nativeEventTarget,
);
dispatchQueue.push({ event, listeners });
}
}
}

三、转导