原生事件是指浏览器中dom节点上触发的事件,一般用
addEventListener挂载到dom上触发的。而在React中由于使用的是Fiber结构,对事件的处理要兼容到Fiber中,所以对原生事件作了一定程度的封装,这就是合成事件SyntheticEvent
1. 实现事件系统需要考虑……
- 模拟实现浏览器事件的捕获和冒泡
- 基于事件对象实现合成事件对象,满足自定义需求,比如阻止冒泡
- 方便扩展
2. React中事件系统流程图
step 1:收集事件
浏览器的事件触发顺序是会先捕获再冒泡,在如图所示,React中,以click为例,首先先找到点击对应的targetElement,收集沿途的click事件,包括onClick和onClickCapture,从targetElement一路向上到root,同时React会维护两个数组,分别是bubble和capture,代表冒泡事件数组和捕获事件数组。在收集到onClick时会push到bubble中,收集到onClickCapture时会unshift到capture中。
step 2: 构造合成事件对象
// 这里先简单的挂载一个阻止冒泡的功能
function createSyntheticEvent(e: Event) {
const syntheticEvent = e as SyntheticEvent;
syntheticEvent.__stopPropagation = false;
const originStopPropagation = e.stopPropagation;
syntheticEvent.stopPropagation = () => {
syntheticEvent.__stopPropagation = true;
if (originStopPropagation) {
originStopPropagation();
}
};
return syntheticEvent;
}
step 3: 遍历capture以及bubble
// 3. 遍历capture
triggerEventFlow(capture, se);
if (!se.__stopPropagation) {
// 4. 遍历bubble
triggerEventFlow(bubble, se);
}
function triggerEventFlow(paths: EventCallback[], se: SyntheticEvent) {
for (let i = 0; i < paths.length; i++) {
const callback = paths[i];
callback.call(null, se);
if (se.__stopPropagation) {
break;
}
}
}
这样,一个简易的合成事件功能就搭起来了!
TODO增加功能,未完待续...