当前位置: 首页 > article >正文

react18中的合成事件与浏览器中的原生事件

React 通过将事件 normalize 以让他们在不同浏览器中拥有一致的属性。

  • 合成事件

    SyntheticEvent 实例将被传递给你的事件处理函数,它是浏览器的原生事件的跨浏览器包装器。除兼容所有浏览器外,它还拥有和浏览器原生事件相同的接口,包括 stopPropagation() 和 preventDefault()。

    如果因为某些原因,当你需要使用浏览器的底层事件时,只需要使用 nativeEvent 属性来获取即可。合成事件与浏览器的原生事件不同,也不会直接映射到原生事件。例如,在 onMouseLeave 事件中 event.nativeEvent 将指向 mouseout 事件。每个 SyntheticEvent 对象都包含以下属性:

    boolean bubbles
    boolean cancelable
    DOMEventTarget currentTarget
    boolean defaultPrevented
    number eventPhase
    boolean isTrusted
    DOMEvent nativeEvent
    void preventDefault()
    boolean isDefaultPrevented()
    void stopPropagation()
    boolean isPropagationStopped()
    void persist()
    DOMEventTarget target
    number timeStamp
    string type
    
import { Component } from "react";
class ClassComp extends Component {
  state = {
    count: 10,
  };
  handleAdd = (e) => {
    this.setState({ count: this.state.count + 1 });
    console.log(e);
  };
  render() {
    const { count } = this.state;
    return (
      <div>
        Class Component
        <p>
          {count}
          <br />
          <button onClick={this.handleAdd}>add</button>
        </p>
      </div>
    );
  }
}
export default ClassComp;

SyntheticBaseEvent是对浏览器原生事件的一个封装,让不同的浏览器的 API 表现一致。浏览器常用的事件基本都有
在这里插入图片描述

  • 原生事件
<body>
  <noscript>You need to enable JavaScript to run this app.</noscript>
  <div id="root"></div>
  <div id="box">
    <button id="btn">提交</button>
  </div>
  <script>
    window.onload = function () {
      const btn = document.getElementById("btn");
      btn.onclick = handleClick;
    };

    function handleClick(e) {
      console.log("🚀 ~ handleClick ~ e:", e);
      console.log("提交成功");
    }
  </script>
</body>

在这里插入图片描述

  • 是要方法经过 bind 处理,那么最后一个实参就是传递的合成事件对象。
handleAdd = (x, e) => {
  console.log("🚀 ~ ClassComp ~ x:", x);
  console.log(e);
};
<button onClick={this.handleAdd.bind(null, 20)}>add</button>;
  • 直接使用箭头函数,获取事件对象和参数
handleAdd2 = (e, x) => {
  console.log("🚀 ~ ClassComp ~ e, x:", e, x);
};
<button onClick={(e) => this.handleAdd2("10", e)}>add2</button>;

事件委托

利用事件的传播机制,将事件绑定到父元素上,通过判断目标元素来执行相应的事件。
传统方法是直接获取元素,然后绑定事件。

  • 事件的捕获和冒泡

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 目标元素阻止冒泡

  • event.stopPropagation()在事件对象中,调用该方法将阻止事件(包括冒泡或捕获)在 DOM 中继续传播。

  • event.stopImmediatePropagation()在事件对象中,调用该方法其他未执行的方法也不会执行了
    在这里插入图片描述
    在这里插入图片描述

  • 最外层阻止冒泡,阻止事件继续向上传播
    在这里插入图片描述
    在这里插入图片描述

React 中合成事件的原理

  • 合成事件绝对不是直接给元素addEventListener进行事件的绑定,而是通过事件委托的方式,给 document 进行事件的绑定。
  • r17 之前的 React 内部通过事件池SyntheticEvent来统一处理浏览器兼容问题,并且将事件委托给 document,且只做了对冒泡阶段的委托。
  • 事件池SyntheticEvent是一个对象,用来包装原生事件。
  • r17 及以后版本,事件池SyntheticEvent是单例模式。都是委托给#root 这个容器,捕获和冒泡都做了委托
  • 事件池SyntheticEvent对象在事件池中缓存,当事件触发时,会从事件池中获取一个对象。
  • 对于没有事件传播机制的事件,才是单独做的事件绑定。例如,onMouseEnter,onMouseLeave,onFocus 等。
  • 在组件渲染的时候,如果发现有 onXxx,onXxxxCapture 这样的属性,不会直接给元素绑定事件,只是把该方法作为属性保存到组件的实例上。然后对#root 容易做了事件绑定。
    在这里插入图片描述
    在这里插入图片描述

React中合成事件的处理原理

在16版本中,合成事件的处理机制,不再是把事件委托给#root元素,而是委托给docunent元素,并且只做了冒泡阶段的委托:在委托的方法中,把onXxx/onMxxcaptare合成事件属性进行执行!
React16中,关于含成事件对象的处理,react内部是基于”事件对象池”做了一个缓存机制!react17及以后,是去掉了这套事件对象池和缓存机制的!


http://www.kler.cn/news/362646.html

相关文章:

  • Navicat 17 新功能 | 数据分析 data profiling
  • oracle imp和exp 导入不同库的用户和表空间
  • java设计模式——装饰者模式
  • 干货|基于React和xlsx库导出表格数据到excel(前端操作)
  • oracle数据库---基本查询(单表查询、多表查询、子查询、分页查询、oracle内置函数、行列转换、集合运算)
  • [实时计算flink]作业开发上线流程及规范
  • 搜维尔科技:使用CyberGlove数据手套控制机械手遥操作拿鸡蛋
  • 如何区分真假Facebook三不限海外户?
  • 立志最细,FreeRtos的中断管理(Interrupt Management)函数,详解!!!
  • idea中添加文件掩码怎么添加
  • zookeeper的作用--有无zookeeper的区别
  • 大模型系列——幻觉
  • 《CUDA编程》9.原子函数的合理使用
  • js 基础补充3
  • 深入浅出:深度学习模型部署全流程详解
  • 【知识科普】Session和Cookie应知应会
  • 创建匿名管道
  • latex表格单独编译成pdf表格
  • Vue 3 的介绍与安装
  • github文件上传与更新
  • Java工具类--截至2024常用http工具类分享
  • qt QGraphicsGridLayout详解
  • 在使用代理IP时,需要注意以下几点:
  • 图像筛选去重、去静止
  • 【设计模式】深入理解Python中的组合模式(Composite Pattern)
  • 《分布式机器学习模式》:解锁分布式ML的实战宝典