React源码系列——合成事件

65 阅读1分钟

原生事件是指浏览器中dom节点上触发的事件,一般用addEventListener挂载到dom上触发的。而在React中由于使用的是Fiber结构,对事件的处理要兼容到Fiber中,所以对原生事件作了一定程度的封装,这就是合成事件SyntheticEvent

1. 实现事件系统需要考虑……

  • 模拟实现浏览器事件的捕获和冒泡
  • 基于事件对象实现合成事件对象,满足自定义需求,比如阻止冒泡
  • 方便扩展

2. React中事件系统流程图

image.png

step 1:收集事件

浏览器的事件触发顺序是会先捕获再冒泡,在如图所示,React中,以click为例,首先先找到点击对应的targetElement,收集沿途的click事件,包括onClickonClickCapture,从targetElement一路向上到root,同时React会维护两个数组,分别是bubblecapture,代表冒泡事件数组和捕获事件数组。在收集到onClick时会pushbubble中,收集到onClickCapture时会unshiftcapture中。

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增加功能,未完待续...