/*
这里React为每一咱们注册的个事件好比onClick,提供了一个方法,来代替了咱们写的回调函数。
*/
dispatchEvent: function (topLevelType, nativeEvent) {
<!--
bookKeeping:是建立了一个对象,这个对象里包含了一个nativeEvent(源事件对象。)一个当前的top事件。好比topAbort。
一个数组 ancestor。用来存储触发元素的祖先层次结构。
在初始条件下。ancestor是空数组,并且nativeEvent是没有赋值的。
-->
var bookKeeping = TopLevelCallbackBookKeeping.getPooled(topLevelType, nativeEvent);
<!-
TopLevelCallbackBookKeeping.getPooled() 是用了React的池化技术,这些在随后的文章中会有,这里,你只须要理解为,该方法创造了一个对象,期内包含了一些辅助属性
--->
try {
<!--
这里真正重要的是 ReactUpdates.batchedUpdates方法。
-->
ReactUpdates.batchedUpdates(handleTopLevelImpl, bookKeeping);
<!--
这里 ReactUpdates.batchedUpdates是采用React的批处理策略,来处理参数。
主要是使用使用bookKeeping做为handleTopLevelImpl的参数来调用该方法
-->
} finally {
<!--
使用池化技术释放了实例以供后续使用。
-->
TopLevelCallbackBookKeeping.release(bookKeeping);
}
}
复制代码
当事件在原事件对象被触发的时候,document会代理到事件,然后dispatchEvent方法就会被执行。此时事件就被分发了。React采用了批处理的方式来处理。node
ReactUpdates.batchedUpdates(handleTopLevelImpl, bookKeeping);
<!--
咱们来讲说
ReactUpdates.batchedUpdates()
这个方法的做用只是以bookKeeping做为handleTopLevelImpl的参数,来执行 handleTopLevelImpl 方法。
-->
复制代码
<!--
handleTopLevelImpl方法最终是执行了下边这个方法
path属性是现代浏览器的事件的一个属性,该属性包含了当前触发元素冒泡的全过程。 chrome有,Safari么有该属性。
现代的浏览器提供了一个方法来返回当前事件的冒泡全过程DOM。event.composedPath()
-->
function handleTopLevelWithoutPath(bookKeeping) {
<!--
getEventTarget方法做用是根据源事件,找到触发源事件的DOM元素。
getFirstReactDOM获得距离触发事件的源对象最近的dom,通常是其自身,也考虑到触发事件的多是text_node,那就要向上找到text_node的父元素返回。
-->
var topLevelTarget = ReactMount.getFirstReactDOM(getEventTarget(bookKeeping.nativeEvent)) || window;
<!--
topLevelTarget是触发事件的当前元素,这里的方法就是为了找到最近的一个DOM元素
-->
while (ancestor) {
bookKeeping.ancestors.push(ancestor);
ancestor = findParent(ancestor);
}
// ancestors 里通常是存了当前触发事件的元素
for (var i = 0; i < bookKeeping.ancestors.length; i++) {
topLevelTarget = bookKeeping.ancestors[i];
<!--
topLevelTarget 是事件触发的源元素。
-->
var topLevelTargetID = ReactMount.getID(topLevelTarget) || '';
<!--
topLevelTargetID源元素的id
-->
<!-
'ReactEventListener._handleTopLevel()方法是核心'
--->
ReactEventListener._handleTopLevel(bookKeeping.topLevelType, topLevelTarget, topLevelTargetID, bookKeeping.nativeEvent, getEventTarget(bookKeeping.nativeEvent));
<!--
ReactEventListener._handleTopLevel方法最终是调用了
ReactEventEmitterMixin.handleTopLevel方法。
而ReactEventEmitterMixin.handleTopLevel方法是调用EventPluginHub.extractEvents方法,生成
合成事件。
然后将合成事件放入队列中,然后一个个的去执行这些事件。
用到的方法是。
EventPluginHub.enqueueEvents(events);
EventPluginHub.processEventQueue(false);
-->
}
}
复制代码
<!--
ReactEventListener._handleTopLevel方法最终是调用了 ReactEventEmitterMixin模块的handleTopLevel方法。
-->
handleTopLevel: function (topLevelType, topLevelTarget, topLevelTargetID, nativeEvent, nativeEventTarget) {
var events = EventPluginHub.extractEvents(topLevelType, topLevelTarget, topLevelTargetID, nativeEvent, nativeEventTarget);
<!--
这里使用EventPluginHu模块来选择不一样的事件插件来将触发的事件处理为合成事件。并将合成事件放入队列。然后执行这些合成事件。
-->
runEventQueueInBatch(events);
}
复制代码
<!--
分别调用EventPluginHub模块的入队方法和执行队列方法。
-->
function runEventQueueInBatch(events) {
EventPluginHub.enqueueEvents(events);
EventPluginHub.processEventQueue(false);
}
复制代码
这里就要说到合成事件了。chrome