React16源码: React中event事件监听绑定的源码实现

React集成StackEdit指南:自托管部署与iframe嵌入实战 Markdown编辑器是技术写作与文档管理的基础工具,而如何将成熟的编辑器能力嵌入到现代前端应用中,是许多开发团队面临的实际问题。StackEdit作为一款功能强大的浏览器端Markdown工作台,不仅支持实时预览、数学公式和流程图,还提供了自托管部署能力,为数据敏感的内部系统提供了灵活的集成方案。在React项目中使用StackEdit,常见路径包括直接iframe引用在线版、通过同源自托管利用localStorage进行数据桥接,以及深度改造源码封装成标准组件。每种方案的集成成本与长期稳定性各有取舍,选 阅读详情

event事件监听


1 )概述

  • 在 react-dom 代码初始化的时候,去注入了平台相关的事件插件
  • 接下去在react的更新过程绑定了事件的操作,在执行到 completeWork 的时候
  • 对于 HostComponent 会一开始就先去执行了 finalizeInitialChildren 这个方法
  • 位置在 packages/react-reconciler/src/ReactFiberCompleteWork.js#L642

2 )源码

定位到 packages/react-dom/src/client/ReactDOMHostConfig.js#L212

找到 finalizeInitialChildren

export function finalizeInitialChildren(
  domElement: Instance,
  type: string,
  props: Props,
  rootContainerInstance: Container,
  hostContext: HostContext,
): boolean {
  setInitialProperties(domElement, type, props, rootContainerInstance);
  return shouldAutoFocusHostComponent(type, props);
}

定位到 packages/react-dom/src/client/ReactDOMComponent.js#L447

找到 setInitialProperties

export function setInitialProperties(
  domElement: Element,
  tag: string,
  rawProps: Object,
  rootContainerElement: Element | Document,
): void {
  const isCustomComponentTag = isCustomComponent(tag, rawProps);
  if (__DEV__) {
    validatePropertiesInDevelopment(tag, rawProps);
    if (
      isCustomComponentTag &&
      !didWarnShadyDOM &&
      (domElement: any).shadyRoot
    ) {
      warning(
        false,
        '%s is using shady DOM. Using shady DOM with React can ' +
          'cause things to break subtly.',
        getCurrentFiberOwnerNameInDevOrNull() || 'A component',
      );
      didWarnShadyDOM = true;
    }
  }

  // TODO: Make sure that we check isMounted before firing any of these events.
  let props: Object;
  switch (tag) {
    case 'iframe':
    case 'object':
      trapBubbledEvent(TOP_LOAD, domElement);
      props = rawProps;
      break;
    case 'video':
    case 'audio':
      // Create listener for each media event
      for (let i = 0; i < mediaEventTypes.length; i++) {
        trapBubbledEvent(mediaEventTypes[i], domElement);
      }
      props = rawProps;
      break;
    case 'source':
      trapBubbledEvent(TOP_ERROR, domElement);
      props = rawProps;
      break;
    case 'img':
    case 'image':
    case 'link':
      trapBubbledEvent(TOP_ERROR, domElement);
      trapBubbledEvent(TOP_LOAD, domElement);
      props = rawProps;
      break;
    case 'form':
      trapBubbledEvent(TOP_RESET, domElement);
      trapBubbledEvent(TOP_SUBMIT, domElement);
      props = rawProps;
      break;
    case 'details':
      trapBubbledEvent(TOP_TOGGLE, domElement);
      props = rawProps;
      break;
    case 'input':
      ReactDOMInput.initWrapperState(domElement, rawProps);
      props = ReactDOMInput.getHostProps(domElement, rawProps);
      trapBubbledEvent(TOP_INVALID, domElement);
      // For controlled components we always need to ensure we're listening
      // to onChange. Even if there is no listener.
      ensureListeningTo(rootContainerElement, 'onChange');
      break;
    case 'option':
      ReactDOMOption.validateProps(domElement, rawProps);
      props = ReactDOMOption.getHostProps(domElement, rawProps);
      break;
    case 'select':
      ReactDOMSelect.initWrapperState(domElement, rawProps);
      props = ReactDOMSelect.getHostProps(domElement, rawProps);
      trapBubbledEvent(TOP_INVALID, domElement);
      // For controlled components we always need to ensure we're listening
      // to onChange. Even if there is no listener.
      ensureListeningTo(rootContainerElement, 'onChange');
      break;
    case 'textarea':
      ReactDOMTextarea.initWrapperState(domElement, rawProps);
      props = ReactDOMTextarea.getHostProps(domElement, rawProps);
      trapBubbledEvent(TOP_INVALID, domElement);
      // For controlled components we always need to ensure we're listening
      // to onChange. Even if there is no listener.
      ensureListeningTo(rootContainerElement, 'onChange');
      break;
    default:
      props = rawProps;
  }

  assertValidProps(tag, props);

  setInitialDOMProperties(
    tag,
    domElement,
    rootContainerElement,
    props,
    isCustomComponentTag,
  );

  switch (tag) {
    case 'input':
      // TODO: Make sure we check if this is still unmounted or do any clean
      // up necessary since we never stop tracking anymore.
      inputValueTracking.track((domElement: any));
      ReactDOMInput.postMountWrapper(domElement, rawProps, false);
      break;
    case 'textarea':
      // TODO: Make sure we check if this is still unmounted or do any clean
      // up necessary since we never stop tracking anymore.
      inputValueTracking.track((domElement: any));
      ReactDOMTextarea.postMountWrapper(domElement, rawProps);
      break;
    case 'option':
      ReactDOMOption.postMountWrapper(domElement, rawProps);
      break;
    case 'select':
      ReactDOMSelect.postMountWrapper(domElement, rawProps);
      break;
    default:
      if (typeof props.onClick === 'function') {
        // TODO: This cast may not be sound for SVG, MathML or custom elements.
        trapClickOnNonInteractiveElement(((domElement: any): HTMLElement));
      }
      break;
  }
}
  • 对于 iframe, object, video, audio, source 这些多媒体节点的初始化绑定
  • 是通过 trapBubbledEvent 来实现的
  • 后续执行到 setInitialDOMProperties, 在这个方法内部
    function setInitialDOMProperties(
      tag: string,
      domElement: Element,
      rootContainerElement: Element | Document,
      nextProps: Object,
      isCustomComponentTag: boolean,
    ): void {
      for (const propKey in nextProps) {
        if (!nextProps.hasOwnProperty(propKey)) {
          continue;
        }
        const nextProp = nextProps[propKey];
        if (propKey === STYLE) {
          // ... 跳过很多代码
        } else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
          // ... 跳过很多代码
        } else if (propKey === AUTOFOCUS) {
          // We polyfill it separately on the client during commit.
          // We could have excluded it in the property list instead of
          // adding a special case here, but then it wouldn't be emitted
          // on server rendering (but we *do* want to emit it in SSR).
          // 注意这里, propKey 是 dom 节点内的 props的配置,如果这个配置在 registrationNameModules 这里
          // registrationNameModules 是通过每一个插件里面每一个 eventTypes 里面
          // 它对应的有 phasedRegistrationNames 的情况下,比如说 onChange, onChangeCapture, 它都是作为它的一个key而存在的
          // 也就是说我们如果在这个 props 上面写了 onChange onClick 这些事件相关的props的话
          // 就会符合这个条件的判断,符合这个条件判断之后, 它会调用一个方法叫做 ensureListeningTo
        } else if (registrationNameModules.hasOwnProperty(propKey)) {
          if (nextProp != null) {
            if (__DEV__ && typeof nextProp !== 'function') {
              warnForInvalidEventListener(propKey, nextProp);
            }
            ensureListeningTo(rootContainerElement, propKey); // rootContainerElement 是 fiberRoot 对应的 container 
          }
        } else if (nextProp != null) {
         // ... 跳过很多代码
        }
      }
    }
    
    • 进入 ensureListeningTo
      function ensureListeningTo(rootContainerElement, registrationName) {
        const isDocumentOrFragment =
          rootContainerElement.nodeType === DOCUMENT_NODE ||
          rootContainerElement.nodeType === DOCUMENT_FRAGMENT_NODE;
        // 如果它是一个document或者fragment,那么它就等于 rootContainerElement
        // 如果它不是,它就等于它的 rootContainerElement.ownerDocument
        // 这个是用来最终要去把事件绑定在哪个地方的
        // 可以确定的是在 react 当中大部分可冒泡的事件都是通过事件代理的形式来进行一个绑定的
        // 也就是说,不是每一个节点都会绑定自己的事件
        // 因为每个节点绑定自己的事件,肯定是性能比较低下的一个操作,而且有可能会导致内存溢出这种情况
        const doc = isDocumentOrFragment
          ? rootContainerElement
          : rootContainerElement.ownerDocument;
        // 调用这个方法
        listenTo(registrationName, doc);
      }
      
      • 进入 listenTo
        // packages/react-dom/src/events/ReactBrowserEventEmitter.js#L126
        export function listenTo(
          registrationName: string,
          mountAt: Document | Element,
        ) {
          // 注意这里
          const isListening = getListeningForDocument(mountAt);
          const dependencies = registrationNameDependencies[registrationName];
        
          // 遍历依赖
          for (let i = 0; i < dependencies.length; i++) {
            const dependency = dependencies[i];
            // 没有这些依赖,则对 dependency 进行事件监听处理
            if (!(isListening.hasOwnProperty(dependency) && isListening[dependency])) {
              switch (dependency) {
                case TOP_SCROLL:
                  // 这个方法监听的是 捕获阶段的事件
                  trapCapturedEvent(TOP_SCROLL, mountAt);
                  break;
                case TOP_FOCUS:
                case TOP_BLUR:
                  trapCapturedEvent(TOP_FOCUS, mountAt);
                  trapCapturedEvent(TOP_BLUR, mountAt);
                  // We set the flag for a single dependency later in this function,
                  // but this ensures we mark both as attached rather than just one.
                  isListening[TOP_BLUR] = true;
                  isListening[TOP_FOCUS] = true;
                  break;
                case TOP_CANCEL:
                case TOP_CLOSE:
                  if (isEventSupported(getRawEventName(dependency))) {
                    trapCapturedEvent(dependency, mountAt);
                  }
                  break;
                case TOP_INVALID:
                case TOP_SUBMIT:
                case TOP_RESET:
                  // We listen to them on the target DOM elements.
                  // Some of them bubble so we don't want them to fire twice.
                  break;
                // 对于其他大部分的事件处理 用冒泡处理
                default:
                  // By default, listen on the top level to all non-media events.
                  // Media events don't bubble so adding the listener wouldn't do anything.
                  const isMediaEvent = mediaEventTypes.indexOf(dependency) !== -1; 
                  // 注意这里排除了 mediaEventTypes,因为一开始就已经对一些 媒体事件处理了
                  if (!isMediaEvent) {
                    trapBubbledEvent(dependency, mountAt); // 这是对常规事件的处理 冒泡
                  }
                  break;
              }
              isListening[dependency] = true;
            }
          }
        }
        
        • 进入 getListeningForDocument

          const alreadyListeningTo = {};
          let reactTopListenersCounter = 0;
          // 这个属性就是用来挂载 container 节点上面去记录这个节点监听了哪些事件的
          // 用这种方式判断是因为 可能不存在这个属性,如果没有,则需要初始化属性
          const topListenersIDKey = '_reactListenersID' + ('' + Math.random()).slice(2);
          function getListeningForDocument(mountAt: any) {
            // In IE8, `mountAt` is a host object and doesn't have `hasOwnProperty`
            // directly.
            if (!Object.prototype.hasOwnProperty.call(mountAt, topListenersIDKey)) {
              mountAt[topListenersIDKey] = reactTopListenersCounter++; // 这里初始化属性
              alreadyListeningTo[mountAt[topListenersIDKey]] = {};
            }
            // 那如果已经有了,我们就返回这个对象, 用来记录这个dom节点它是否监听了哪些事件的
            return alreadyListeningTo[mountAt[topListenersIDKey]];
          }
          
        • 对于 mediaEventTypes 和媒体相关的事件

          // packages/react-dom/src/events/DOMTopLevelEventTypes.js#L155
          export const mediaEventTypes = [
            TOP_ABORT,
            TOP_CAN_PLAY,
            TOP_CAN_PLAY_THROUGH,
            TOP_DURATION_CHANGE,
            TOP_EMPTIED,
            TOP_ENCRYPTED,
            TOP_ENDED,
            TOP_ERROR,
            TOP_LOADED_DATA,
            TOP_LOADED_METADATA,
            TOP_LOAD_START,
            TOP_PAUSE,
            TOP_PLAY,
            TOP_PLAYING,
            TOP_PROGRESS,
            TOP_RATE_CHANGE,
            TOP_SEEKED,
            TOP_SEEKING,
            TOP_STALLED,
            TOP_SUSPEND,
            TOP_TIME_UPDATE,
            TOP_VOLUME_CHANGE,
            TOP_WAITING,
          ];
          
        • 进入 trapCapturedEvent

          export function trapCapturedEvent(
            topLevelType: DOMTopLevelEventType,
            element: Document | Element,
          ) {
            if (!element) {
              return null;
            }
            // 注意这里,根据是否是 Interactive 类型的事件,调用的不同的回调,最终赋值给 dispatch
            const dispatch = isInteractiveTopLevelEventType(topLevelType)
              ? dispatchInteractiveEvent
              : dispatchEvent;
          
            addEventCaptureListener(
              element,
              getRawEventName(topLevelType),
              // Check if interactive and wrap in interactiveUpdates
              dispatch.bind(null, topLevelType),
            );
          }
          
          • 进入 isInteractiveTopLevelEventType
            const SimpleEventPlugin: PluginModule<MouseEvent> & {
              isInteractiveTopLevelEventType: (topLevelType: TopLevelType) => boolean,
            } = {
              eventTypes: eventTypes,
              // 注意这里的 topLevelEventsToDispatchConfig 一开始是一个空的对象
              // 在调用 addEventTypeNameToConfig 时候加入的
              // 这个方法是检测 
              isInteractiveTopLevelEventType(topLevelType: TopLevelType): boolean {
                const config = topLevelEventsToDispatchConfig[topLevelType];
                return config !== undefined && config.isInteractive === true;
              },
              // ... 跳过其他
            }
            
            • 进入 addEventTypeNameToConfig
              function addEventTypeNameToConfig(
                [topEvent, event]: EventTuple,
                isInteractive: boolean,
              ) {
                const capitalizedEvent = event[0].toUpperCase() + event.slice(1);
                const onEvent = 'on' + capitalizedEvent;
              
                // 注意这个数据结构
                const type = {
                  phasedRegistrationNames: {
                    bubbled: onEvent,
                    captured: onEvent + 'Capture',
                  },
                  dependencies: [topEvent],
                  isInteractive, // 注意这里的标识
                };
                eventTypes[event] = type;
                topLevelEventsToDispatchConfig[topEvent] = type; // 这里进行注入
              }
              
              • 关于这里的 isInteractive 标识的来源
                interactiveEventTypeNames.forEach(eventTuple => {
                  addEventTypeNameToConfig(eventTuple, true);
                });
                nonInteractiveEventTypeNames.forEach(eventTuple => {
                  addEventTypeNameToConfig(eventTuple, false);
                });
                
                • 其中 interactiveEventTypeNames
                  • 参考 packages/react-dom/src/events/SimpleEventPlugin.js#L59
                • 其中 nonInteractiveEventTypeNames
                  • 参考 packages/react-dom/src/events/SimpleEventPlugin.js#L95
                • 上面两个数组对应 dom 原生的事件, 它们的区别是什么呢
                  • 这些事件去调用了设置的事件回调之后,里面如果有 setState
                  • 那么创建了update去计算的 expirationTime 会有 interactive 和 nonInteractive 的区分
                  • 它们的区别在 expirationTime,interactive的会比较的小
                  • 也就是说它的优先级会比较的高,它需要优先被执行
                  • 因为它是一个用户交互相关的事件,希望是用户比如说点了一个按钮之后
                  • 立马可以得到反馈, 因为它需要被优先执行的
          • 进入 addEventCaptureListener
            // 两者区别是第三个参数,bubble 是 false, capture 是 true
            export function addEventBubbleListener(
              element: Document | Element,
              eventType: string,
              listener: Function,
            ): void {
              element.addEventListener(eventType, listener, false); 
            }
            
            // 注意这里
            export function addEventCaptureListener(
              element: Document | Element,
              eventType: string,
              listener: Function,
            ): void {
              element.addEventListener(eventType, listener, true); // 主要是绑定 dom 原生事件
            }
            
        • 同样对于 trapBubbledEvent 也同上类似,这里不再赘述

reactphp-eventsource:简单的EventSource客户端实现,可使用ReactPHP消耗流式服务器发送的事件(SSE) 线索/ reactphp-eventsource 事件驱动的EventSource客户端,从任何基于HTML5服务器发送的事件(SSE)服务器接收流消息。 注意:该项目处于早期Alpha阶段! 随时报告您遇到的任何问题。 目录 快速入门示例 ,您可以使用以下代码从任何服务器发送事件(SSE)服务器端点流式传输消息: $ loop = Factory :: create (); $ es = new Clue \ React \ EventSource \ EventSource ( 'https://example.com/stream.php' , $ loop ); $ es -> on ( 'message' , function ( Clue \ React \ EventSource \ MessageEvent $ message ) { //$data = j 立即下载

相关推荐

从零开始学习信号完整性(SIPI)--1 简介

信号完整性就是研究如何让驱动芯片发出的信号经过传输通道被接收芯片正确接收的学问。 信号完整性包含了三个要素: 信号:是被传输的主体,我们首先要了解、熟悉信号的特性。 芯片:分为驱动芯片和接收芯片,信号完整性工程师就是要实现信号在驱动芯片和接收芯片之间的正确传输。 传输通道:是传输信号的介质,是信号所走的“路”。如何实现信号的正确传输呢?那就要信号完整性工程师为信号“修路”、“搭桥”。

qq_29476769的博客 4万+

在react中使用event(事件对象),如何使用,注意事项和react中如何定义和使用函数?

定义使用方式和function一样的区别在于箭头函数没有自己的this指向,只会向上继承父级的this指向,如果父级没有this指向还会继续向上检索执行后的效果。

Youyzq的博客 2400

Cursor AI对话历史丢失?开源工具一键恢复项目聊天记录

在软件开发中,数据持久化与工作区管理是保障开发效率与上下文连续性的基础技术。其核心原理在于通过文件系统路径、数据库存储等机制,将应用状态与用户数据持久化关联。对于依赖AI辅助编程的开发者而言,对话历史是宝贵的项目上下文资产,记录了关键的算法思路、API使用范例和问题解决方案。然而,当开发工具(如基于VS Code的Cursor)采用基于项目绝对路径的工作区隔离机制时,项目路径的变更会导致历史对话看似“丢失”,实则是被隔离在了旧路径对应的数据沙箱中。这直接影响了开发体验与知识沉淀的效率。cursor-chat

weixin_26775679的博客 831

React中events的踩坑指南

本文介绍react项目中如何创建events来进行跨组件事件触发重点讲解自定义参数传递,和如何拿到最新的state值🌟。

分享前端知识,记录前端进阶 908

不报辅导班一次性通过CISSP经验分享(附:备考教材、往年真题及个人学习笔记)

CISSP(Certified Information Systems Security Professional,注册信息系统安全专家)是一种国际认可的信息安全管理专业认证。CISSP认证由国际信息系统安全认证联盟(ISC)²提供,是全球范围内最受尊敬的信息安全专业认证之一。CISSP认证涵盖了信息安全的多个领域,包括安全和风险管理、资产安全、安全工程、通信与网络安全、身份和访问管理、安全评估与测试、安全运营。要获得CISSP认证,考生需要通过CISSP考试。

所有成功的背后,都是痛苦的坚持,所有的痛苦,都是傻瓜般的不放弃! 8135

从零到一:使用阿里云百炼搭建企业级 AI Agent 完全实战手册(2026超详细版)

本文是一份企业级AI Agent构建手册,主要面向企业技术负责人、AI产品经理和后端开发工程师。手册详细介绍了如何在阿里云百炼平台上搭建企业智能体应用的全流程,包括环境准备、知识库构建、智能体创建、工具集成、工作流编排等核心环节。重点内容包括: 准备工作:阿里云账号注册、百炼服务开通、免费额度领取、API Key管理 知识库构建:文档格式要求、内容优化原则、RAG系统搭建 智能体开发:Agent创建、工具集成、复杂业务工作流设计 生产部署:多渠道接入、监控运维、安全治理 成本控制:Token预算管理、选型决

u010323587的专栏 1106

React-监听事件

事件的监听与移除 addEventListener removeEventListener

kelly0721的博客 7949

Python经典编程习题100例:第25例:求各个阶乘的和

不要自卑,去提升实力 互联网行业谁技术牛谁是爹 如果文章可以带给你能量,那是最好的事!请相信自己 加油o~ 本人初学Python,只为熟悉语法编写,大神请勿理会 点击下面链接 Python经典编程100例习题汇总 题目描述: 求1+2!+3!+…+20!的和。 解题思路: > 调用math模块中的factorial函数 代码: import math sum=0 for i in range(1,21): sum+=math.factorial(i) print(sum) ..

优快云 精品推荐 2736

前端写SSE请求,实现live Tail效果

实现像idea控制台输出日志功能, 所以需要在后端拿日志数据, 数据量大且快, 点击开关开始live Tail,用了throttle控制渲染次数和react-window做虚拟滚动

是还不成熟的开发人员啊 661

OpenHarmony WiFi子系统全解析:从架构到代码实现(大合集)

头文件路径[相对路径][相对路径][相对路径][相对路径]// 网络配置结构 (wifi_device_config.h)// SSID字符串// 预共享密钥// 安全类型// 网络ID// 优先级// 是否隐藏网络// 扫描信息结构 (wifi_scan_info.h)// SSID// BSSID (MAC地址)// 安全类型int rssi;// 信号强度// 频率// 信道宽度// 时间戳// 连接信息结构 (wifi_linked_info.h)

m0_67505153的博客 1060

电压跟随器在ADC采样电路中的作用分析

电压跟随器在ADC采集系统中扮演关键角色,它能解决分压电路因ADC输入阻抗导致的电压误差问题。通过运放构成的电压跟随器可隔离信号源与负载,保证采样精度,尤其适用于高阻抗传感器或高速采样场景。工程应用中需注意运放带宽、轨对轨输出能力及抗干扰设计。合理使用电压跟随器能显著提升信号完整性,在复杂电子系统中成为不可或缺的"信号桥梁。

硬核科技 659

React16源码: React中event事件触发的源码实现

它是出于对各种系统的一个兼容调用的一个方法来进行一个 Polyfill。,这个 target 就是我们 event 对象上面的 target。我们真正的每一个节点上面,如果有绑定这个事件,它就会调用它的一个回调。这就是事件触发的整个流程, 非常的繁琐,有各种各样的方法,嵌套的调用。到这里为止,这边的 listener 就已经被调用了。batchedUpdates 里面调用的方法是。

Wang的专栏 1976

YOLOv9改进策略 | Conv篇 | 2024最新ECCV最新大感受野的小波卷积WTConv助力YOLOv9有效涨点

本文给大家带来的改进机制是一种新的卷积层,称为WTConv(小波卷积层),它利用小波变换(WT)来解决卷积神经网络(CNN)在实现大感受野时遇到的过度参数化问题。WTConv的主要目的是通过对输入数据的不同频率带进行处理,使CNN能够更有效地捕捉局部和全局特征,WTConv成功解决了CNN在感受野扩展中的参数膨胀问题,提供了一种更为高效、鲁棒且易于集成的卷积层解决方案,我将其用于二次创新YOLOv9中的RepNCSPELAN4机制可以减少一定的参数量和计算量,达到一个可观的轻量化作用。

Snu77的博客 1544

Hippy React 终端事件(Native Event)完整指南:从 Hippy.on 到 EventBus 的全局事件管理实战

本篇技术指南聚焦 Hippy 跨端框架中 **Hippy React 终端事件(全局事件)** 的管理机制:屏幕旋转、网络变化、容器尺寸改变、JS 引擎销毁这类"发给整个业务"而非单个 UI 节点的事件,应如何在前端监听、分发与卸载。读完本文,你将掌握 `Hippy.on/off/emit`、`HippyEventEmitter` 与 `EventBus` 三套 API 的完整用法、各自的适用场景

gitblog_00066的博客 1091

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

React与Unity WebGL双向通信:原理、实现与性能优化

在现代Web开发中,前端框架与3D渲染引擎的深度整合已成为构建复杂可视化应用的关键需求。其核心原理在于建立JavaScript与WebAssembly之间的高效通信桥梁,通过事件驱动与消息传递机制实现数据同步。这一技术方案的核心价值在于能够将React声明式UI的高效状态管理与Unity强大的实时渲染能力相结合,从而突破传统Web应用在交互体验上的局限。在实际工程实践中,开发者常需处理序列化、性能优化与跨平台兼容性等挑战,尤其是在数字孪生、在线教育、互动营销等需要高保真3D展示与复杂业务逻辑并行的应用场景中

蓝色妖姬 1022

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

qiankun React 绑定指南:用 `<MicroApp>` 组件在 React 宿主中挂载与管理微应用

`@qiankunjs/react` 是 qiankun 官方提供的 React 生态绑定包,它把 [`loadMicroApp`](https://link.gitcode.com/i/bc6747496ded3d2bb7795b17e2afc7c4) 封装成一个声明式的 `<MicroApp>` 组件,让宿主应用可以在 React 组件树中像使用普通组件一样挂载、更新和卸载微应用,并额外提供了

gitblog_00106的博客 482

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

React 源码深读:SyntheticEvent 合成事件系统的演进与底层分发

在 React 应用中,我们无时无刻不在编写。很多初学者以为 React 只是简单地把这些事件监听器直接绑定到了对应的真实<button>DOM 节点上。然而,在底层架构中,React 从未将事件直接绑在目标 DOM 上,而是构建了一套庞大而严密的documentrootDOM深入理解 SyntheticEvent 的演进与派发链路,是彻底排查跨微前端事件冲突与复杂捕获冒泡 Bug 的根本底气。

2301_77785315的博客 232

ok-ww鸣潮后台自动战斗工具:2条路径从安装到自动刷日常

ok-ww是一款鸣潮自动化工具:基于图像识别模拟键鼠操作,在后台帮你跑每日任务、自动战斗、刷声骸,运行期间你可以正常用电脑。它不读取游戏内存、不修改游戏文件。仅支持Windows平台,游戏分辨率需为16:9(最低1280×720,最高支持4K)。 ## 能力速览:这款鸣潮自动化工具能做什么 | 功能 | 能做什么 | |------|---------| | 一键日常(DailyTask) |

gitblog_00040的博客 837

react相关面试题

react相关面试题

weixin_47808575的博客 1057

tldraw 核心引擎 API 完全指南:解读 @tldraw/editor 包公开接口与源码实现

本指南以仓库中 [packages/editor/api-report.api.md](https://link.gitcode.com/i/9d5bb4fc7bcf70023c230ed6f6e5cf32) 这份由 API Extractor 自动生成的官方 API 报告为主体,结合 [packages/editor/src](https://link.gitcode.com/i/230560b

gitblog_01006的博客 763

React 事件处理函数存入 Ref:稳定订阅模式与 useEffectEvent 实战(next-shadcn-dashboard-starter 最佳实践解析)

本文围绕 next-shadcn-dashboard-starter 仓库内置的 Vercel React 最佳实践规则 [advanced-event-handler-refs.md](https://link.gitcode.com/i/c6464c7021d42685547f0dddcaead1b0),系统讲解"把事件处理函数(Event Handler)存入 Ref,以获得稳定订阅"这一高

gitblog_00445的博客 486

如何挑选 Qwen3-ASR 1.7B 最佳版本?fp16 / q8_0 / q4_k 三种量化构建终极对比指南

正在为 **Qwen3-ASR 1.7B** 语音识别模型挑选合适的构建版本吗?这个项目提供了三种量化格式:`fp16`、`q8_0` 和 `q4_k`,均以 `.oasr` 原生封装打包,可在 OpenASR 运行时中**无需 Python** 直接执行语音转写。本文用一张对比表 + 清晰的选择逻辑,帮你在 1 分钟内做出正确决策:多数用户选 **q8_0** 就对了。 ## 先了解:这个仓库

gitblog_00065的博客 876

react-map-gl 入门指南:为 Mapbox GL JS 与 MapLibre GL JS 打造的响应式 React 地图组件

react-map-gl 是一套专为 `mapbox-gl`、`maplibre-gl` 及兼容库设计的 React 组件库,它把底层地图库的命令式 API 完全封装为声明式、可受控的 React 接口,让地图状态真正由 React 掌控。本文将以 [docs/README.md](https://link.gitcode.com/i/6bec0e9b87ae2b7acc9ef5239277e41

gitblog_00511的博客 1046

Inferno 入门与原理指南:React 风格的极速虚拟 DOM 库(v9)完整上手

Inferno 是一个以“运行时性能最大化”为核心目标的 React 风格前端库,面向客户端与服务器端的高性能 UI 渲染。本篇文章以项目 [README.md](https://link.gitcode.com/i/602cab80041457048e743096e7274a9a) 为主干,结合仓库内 [packages/inferno](https://link.gitcode.com/i/b

gitblog_00762的博客 1161

ahooks 深入解析 useClickAway:监听元素外部点击事件的最佳实践

`useClickAway` 是 ahooks(A high-quality & reliable React Hooks library)中用于**监听目标元素外点击事件**的核心 Hook,广泛用于实现下拉菜单、弹窗、抽屉、气泡卡片等组件的"点击外部关闭"交互。本文基于仓库内 [useClickAway 中文文档](https://link.gitcode.com/i/8d31617f7d40

gitblog_00251的博客 510

Ghost博客中文输入吞字之谜:React受控组件与输入法组合事件修复

中文输入法在网页端工作的核心机制是组合事件,包括compositionstart、compositionupdate与compositionend,三个阶段共同完成从拼音到汉字的转换。然而在前端框架中,受控组件默认将输入框的每次变动都视为最终状态,导致拼音拼写阶段的中间值被同步渲染,出现文字被吞、拼音残留甚至光标错乱等异常。尤其在以React构建的富文本编辑器和博客平台中,自动保存与状态同步放大了这一冲突。本文从输入法事件原理切入,剖析Ghost博客后台编辑器中文输入BUG的根因,并结合工程实践给出基于us

weixin_34226182的博客 499
上一篇: React16源码: React中event事件系统初始化源码实现
下一篇: React16源码: React中event事件触发的源码实现
Wang's Blog
博客等级 码龄12年 7434粉丝 2421原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值