続き
enqueuePutListener
function enqueuePutListener(inst, registrationName, listener, transaction) {
...,
var containerInfo = inst._nativeContainerInfo;
var doc = containerInfo._ownerDocument;
if (!doc) {
// Server rendering.
return;
}
listenTo(registrationName, doc);
transaction.getReactMountReady().enqueue(putListener, {
inst: inst,
registrationName: registrationName,
listener: listener,
});
}
listenTo
var listenTo = ReactBrowserEventEmitter.listenTo;
ReactBrowserEventEmitter
var ReactBrowserEventEmitter = assign({}, ReactEventEmitterMixin, {
...,
listenTo: function(registrationName, contentDocumentHandle) {
var mountAt = contentDocumentHandle;
var isListening = getListeningForDocument(mountAt);
var dependencies =
EventPluginRegistry.registrationNameDependencies[registrationName];
var topLevelTypes = EventConstants.topLevelTypes;
...,
},
);
処理が長いので分けて見ていきます。
registrationName=onChange, contentDocumentHandle=documentです。
dependenciesは以下のとおりです。
ChangeEventPlugin.js
var eventTypes = {
change: {
phasedRegistrationNames: {
bubbled: keyOf({onChange: null}),
captured: keyOf({onChangeCapture: null}),
},
dependencies: [
topLevelTypes.topBlur,
topLevelTypes.topChange,
topLevelTypes.topClick,
topLevelTypes.topFocus,
topLevelTypes.topInput,
topLevelTypes.topKeyDown,
topLevelTypes.topKeyUp,
topLevelTypes.topSelectionChange,
],
},
};
EventConstantsも見てみます。
EventConstants.js
var topLevelTypes = keyMirror({
topAbort: null,
topAnimationEnd: null,
topAnimationIteration: null,
topAnimationStart: null,
topBlur: null,
topCanPlay: null,
topCanPlayThrough: null,
topChange: null,
topClick: null,
topCompositionEnd: null,
topCompositionStart: null,
topCompositionUpdate: null,
topContextMenu: null,
topCopy: null,
topCut: null,
topDoubleClick: null,
topDrag: null,
topDragEnd: null,
topDragEnter: null,
topDragExit: null,
topDragLeave: null,
topDragOver: null,
topDragStart: null,
topDrop: null,
topDurationChange: null,
topEmptied: null,
topEncrypted: null,
topEnded: null,
topError: null,
topFocus: null,
topInput: null,
topInvalid: null,
topKeyDown: null,
topKeyPress: null,
topKeyUp: null,
topLoad: null,
topLoadedData: null,
topLoadedMetadata: null,
topLoadStart: null,
topMouseDown: null,
topMouseMove: null,
topMouseOut: null,
topMouseOver: null,
topMouseUp: null,
topPaste: null,
topPause: null,
topPlay: null,
topPlaying: null,
topProgress: null,
topRateChange: null,
topReset: null,
topScroll: null,
topSeeked: null,
topSeeking: null,
topSelectionChange: null,
topStalled: null,
topSubmit: null,
topSuspend: null,
topTextInput: null,
topTimeUpdate: null,
topTouchCancel: null,
topTouchEnd: null,
topTouchMove: null,
topTouchStart: null,
topTransitionEnd: null,
topVolumeChange: null,
topWaiting: null,
topWheel: null,
});
var EventConstants = {
topLevelTypes: topLevelTypes,
PropagationPhases: PropagationPhases,
};
果てしなく多い!!
getListeningForDocument
var reactTopListenersCounter = 0;
var topListenersIDKey = '_reactListenersID' + String(Math.random()).slice(2);
function getListeningForDocument(mountAt) {
// In IE8, `mountAt` is a host object and doesn't have `hasOwnProperty`
// directly.
if (!Object.prototype.hasOwnProperty.call(mountAt, topListenersIDKey)) {
mountAt[topListenersIDKey] = reactTopListenersCounter++;
alreadyListeningTo[mountAt[topListenersIDKey]] = {};
}
return alreadyListeningTo[mountAt[topListenersIDKey]];
}
なんか色々設定してobjectを返しています。
listenTo
続き
for (var i = 0; i < dependencies.length; i++) {
var dependency = dependencies[i];
if (!(
isListening.hasOwnProperty(dependency) &&
isListening[dependency]
)) {
if (dependency === topLevelTypes.topWheel) {
..., // topWheelはないので無視
} else if (dependency === topLevelTypes.topScroll) {
..., // topScrollもないので無視
} else if (dependency === topLevelTypes.topFocus ||
dependency === topLevelTypes.topBlur) {
if (isEventSupported('focus', true)) {
ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(
topLevelTypes.topFocus,
'focus',
mountAt
);
ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(
topLevelTypes.topBlur,
'blur',
mountAt
);
} else if (isEventSupported('focusin')) {
ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(
topLevelTypes.topFocus,
'focusin',
mountAt
);
ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(
topLevelTypes.topBlur,
'focusout',
mountAt
);
isListening[topLevelTypes.topBlur] = true;
isListening[topLevelTypes.topFocus] = true;
}
} else if (topEventMapping.hasOwnProperty(dependency)) {
ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(
dependency,
topEventMapping[dependency],
mountAt
);
}
isListening[dependency] = true;
}
},
eventのdependencyを取得してそれをすべてlistenerとして登録しています。
最終的にCallbackQueue.callbackとCallbackQueue.contextsに追加して終了しています。
あとは、DOMLazyTreeを作成していくだけです。
うーむ、CallbackQueueがどのように処理されているかがいまだわからない。。