Skip to content

06.收集注册的函数

packages/react-dom-bindings/src/events/DOMPluginEventSystem.js

js
import { HostComponent } from 'react-reconciler/src/ReactWorkTags';
import getListener from './getListener';

/**
 * 累积单阶段监听器
 * @param {Fiber} targetFiber 目标Fiber实例
 * @param {string} reactName React事件名称
 * @param {string} nativeEventType 原生事件类型
 * @param {boolean} isCapturePhase 是否在捕获阶段
 */
export function accumulateSinglePhaseListeners(
  targetFiber, reactName, nativeEventType, isCapturePhase
) {
  const captureName = reactName + 'Capture';
  const reactEventName = isCapturePhase ? captureName : reactName;
  const listeners = [];
  let instance = targetFiber;
  while (instance !== null) {
    const { stateNode, tag } = instance;
    if (tag === HostComponent && stateNode !== null) {
      const listener = getListener(instance, reactEventName);
      if (listener) {
        listeners.push(createDispatchListener(instance, listener, stateNode));
      }
    }
    instance = instance.return;
  }
  return listeners;
}

/**
 * 创建分发监听器
 * @param {Fiber} instance Fiber实例
 * @param {Function} listener 监听器函数
 * @param {Element} currentTarget 当前目标元素
 */
function createDispatchListener(instance, listener, currentTarget) {
  return { instance, listener, currentTarget }
}

packages/react-dom-bindings/src/events/getListener.js

js
import { getFiberCurrentPropsFromNode } from "../client/ReactDOMComponentTree";

/**
 * 从给定的React实例中获取指定事件的监听函数。
 *
 * @param {Object} instance - React实例。
 * @param {string} registrationName - 注册的事件名(例如,'onClick')。
 * @returns {Function|null} - 返回该事件的监听函数,如果不存在则返回null。
 */
export default function getListener(instance, registrationName) {
  // 从实例中取出状态节点
  const { stateNode } = instance;
  // 如果状态节点不存在,返回null
  if (stateNode === null)
    return null;
  // 使用ReactDOMComponentTree模块的getFiberCurrentPropsFromNode函数,获取状态节点当前的props
  const props = getFiberCurrentPropsFromNode(stateNode);
  // 如果props不存在,返回null
  if (props === null)
    return null;
  // 从props中获取对应事件名的监听函数
  const listener = props[registrationName];
  // 返回监听函数,如果不存在,此处将返回undefined
  return listener;
}

packages/react-dom-bindings/src/client/ReactDOMComponentTree.js

js
export function getFiberCurrentPropsFromNode(node) {
    return node[internalPropsKey] || null;
}

基于 VitePress 构建