react的合成事件

react的合成事件

在没有合成事件前,前端是如何处理事件的呢
假设一个列表的ul标签有一万个li标签,需要添加点击事件,通过点击li获取标签中的文本 应该如何操作:

1.在每个li标签上添加onClick事件 有一万个就需要添加一万个事件,这个是很不友好的,而且影响性能,如何优化呢
通过事件委托,通过将事件绑定到ul上这样的方式,当li事件被点击时,由事件冒泡到父级ul上,并在父级的onClick事件中确认是哪一个li标签
的点事件

<ul id='ii'>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>...</li>
</ul>

let ul = document.getElementById('ii');
ul.onClick = function(event){
  e=e || window.event;
  return e.target || e.srcElement;
   alert(target.innerHTML);
}

react的合成事件:
React 合成事件(SyntheticEvent)是 React 模拟原生 DOM 事件所有能力的一个事件对象,即浏览器原生事件的跨浏览器包装器。它根据 W3C 规范 来定义合成事件,兼容所有浏览器,拥有与浏览器原生事件相同的接口。

在 React 中,所有事件都是合成的,不是原生 DOM 事件,但可以通过 e.nativeEvent 属性获取 DOM 事件。 比如:

const button = <button onClick={handleClick}>react 按钮</button>
const handleClick = (e) => console.log(e.nativeEvent); //原生事件对象

那么 React 为什么使用合成事件?
1.进行浏览器兼容,实现更好的跨平台
React 采用的是顶层事件代理机制,能够保证冒泡一致性,可以跨浏览器执行。React 提供的合成事件用来抹平不同浏览器事件对象之间的差异,将不同平台事件模拟合成事件。

2.避免垃圾回收
事件对象可能会被频繁创建和回收,因此 React 引入事件池,在事件池中获取或释放事件对象。即 React 事件对象不会被释放掉,而是存放进一个数组中,当事件触发,就从这个数组中弹出,避免频繁地去创建和销毁(垃圾回收)。

3.方便事件统一管理和事务机制

React合成事件原理

React合成事件的工作原理大致可以分为两个阶段:
事件绑定
事件触发
在React17之前,React是把事件委托在document上的,React17及以后版本不再把事件委托在document上,而是委托在挂载的容器上了,本文以16.x版本的React为例来探寻React的合成事件。当真实的dom触发事件时,此时构造React合成事件对象,按照冒泡或者捕获的路径去收集真正的事件处理函数,在此过程中会先处理原生事件,然后当冒泡到document对象后,再处理React事件。

import React from 'react';

class Demo extends React.Component {
  parentRef: React.RefObject<any>;
  childRef: React.RefObject<any>;

  constructor(props) {
    super(props);
    this.parentRef = React.createRef();
    this.childRef = React.createRef();
  }

  componentDidMount() {
    document.addEventListener(
      'click',
      () => {
        console.log(`document原生事件捕获`);
      },
      true,
    );
    document.addEventListener('click', () => {
      console.log(`document原生事件冒泡`);
    });
    this.parentRef.current.addEventListener(
      'click',
      () => {
        console.log(`父元素原生事件捕获`);
      },
      true,
    );
    this.parentRef.current.addEventListener('click', () => {
      console.log(`父元素原生事件冒泡`);
    });
    this.childRef.current.addEventListener(
      'click',
      () => {
        console.log(`子元素原生事件捕获`);
      },
      true,
    );
    this.childRef.current.addEventListener('click', () => {
      console.log(`子元素原生事件冒泡`);
    });
  }

  handleParentBubble = () => {
    console.log(`父元素React事件冒泡`);
  };

  handleChildBubble = () => {
    console.log(`子元素React事件冒泡`);
  };

  handleParentCapture = () => {
    console.log(`父元素React事件捕获`);
  };

  handleChileCapture = () => {
    console.log(`子元素React事件捕获`);
  };

  render() {
    return (
      <div
        ref={this.parentRef}
        onClick={this.handleParentBubble}
        onClickCapture={this.handleParentCapture}
      >
        <div
          ref={this.childRef}
          onClick={this.handleChildBubble}
          onClickCapture={this.handleChileCapture}
        >
          事件处理
        </div>
      </div>
    );
  }
}

export default demo;

注意在react17中
自React发布以来, 一直自动进行事件委托。当 document 上触发 DOM 事件时,React 会找出调用的组件,然后 React 事件会在组件中向上 “冒泡”。但实际上,原生事件已经冒泡出了 document 级别,React 在其中安装了事件处理器。但是,这就是逐步升级的困难所在。

在 React 17 中,React 将不再向 document 附加事件处理器。而会将事件处理器附加到渲染 React 树的根 DOM 容器中

在 React 16 或更早版本中,React 会对大多数事件执行 document.addEventListener()。React 17 将会在底层调用 rootNode.addEventListener()

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

浪里个浪里个浪里个浪

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

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

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

打赏作者

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

抵扣说明:

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

余额充值