经典的事件系统分成两大块,绑定事件与分派事件,在浏览器中,分派事件很少人会直接dispatchEvent。因为创建一个DOM 事件是非常复杂的事情,不同的事件对象对应不同的事件构造器,传参也五花八门。因为分派事件基本上用户行为触发,比如我们点击了某个元素,恰逢在这上方绑定了点击事件,于是触发了。
React的绑定事件是在JSX 中进行,换言之, render时,props的onXXX事件就被收集起来,进行绑定。在jQuery时,人们发明了事件委托,将可以冒泡的事件挂在document或window对象上,进行统一的监听,实现高性能的事件系统。现在我们可以无视IE8 ,因此对不可冒泡的事件可以使用事件捕获,对能冒泡的事件使用事件冒泡,也是放在顶层对象 上进行监听。
function trapBubbledEvent(topLevelType, element) {
//by 司徒正美
trapEventForPluginEventSystem(element, topLevelType, false);
}
function trapCapturedEvent(topLevelType, element) {
trapEventForPluginEventSystem(element, topLevelType, true);
}
大家可能觉得很奇怪,浏览器的dom.addEventListener(type, fn, capture)
怎么也要三个参数, 原因是fn是一个统一调度的方法,因此可省掉一个。而冒泡与捕获则通过不同的方法做区分,实际干活的是trapEventForPluginEventSystem。
trapEventForPluginEventSystem根据事件名进行分大三类,DiscreteEvent,UserBlockingEvent,ContinuousEvent,选出不同的事件派发器。
function trapEventForPluginEventSystem(element, topLevelType, capture) {
//by 司徒正美
var listener;
switch (getEventPriority(topLevelType)) {
case DiscreteEvent:
listener = dispatchDiscreteEvent.bind(null, topLevelType, PLUGIN_EVENT_SYSTEM);
break;
case UserBlockingEvent:
listener = dispatchUserBlockingUpdate.bind(null, topLevelType, PLUGIN_EVENT_SYSTEM);
break;
case ContinuousEvent: //by 司徒正美
default:
listener = dispatchEvent.bind(null, topLevelType, PLUGIN_EVENT_SYSTEM);
break;
}
var rawEventName = getRawEventName(topLevelType);
if (capture) {
addEventCaptureListener(element, rawEventName, listener);
} else {
addEventBubbleListener(element, rawEventName, listener);
}
}
DiscreteEvent 离散事件. 例如blur、focus、 click、 submit、 touchStart. 这些事件都是离散触发的。
UserBlockin