/*
這裏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