深入了解React中的合成事件

 更新时间:2023年02月20日 10:59:01   作者:跑跑快跑  
React 中的事件,是对原生事件的封装,叫做合成事件。这篇文章主要通过几个简单的示例为大家详细介绍一下React中的合成事件,感兴趣的可以了解一下

1 事件三个阶段 捕获、目标、处理 (具体百度,后面有空补全)

2 示例

import React from "react";
 
class Test extends React.Component {
  parentRef;
  childRef;
  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 = (e) => {
    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 Test;

执行顺序

只留子元素修改代码

import React from "react";
 
class Test extends React.Component {
  parentRef;
  childRef;
  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 = (e) => {
    console.log(`子元素React事件冒泡`);
  };
  // handleParentCapture = () => {
  //   console.log(`父元素React事件捕获`);
  // };
  handleChileCapture = () => {
    console.log(`子元素React事件捕获`);
  };
  render() {
    return (
      <div
        ref={this.childRef}
        onClick={this.handleChildBubble}
        onClickCapture={this.handleChileCapture}
      >
        事件处理测试
      </div>
    );
    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 Test;

document原生事件捕获--》子元素React事件捕获--》子元素原生事件捕获--》子元素原生事件冒泡--》子元素React事件冒泡--》document原生事件冒泡

从这个执行顺序来看,react事件捕获执行比原生事件捕获早,但是原生事件冒泡执行比react事件冒泡快。

所有的react捕获事件执行完毕之后才会去执行原生的捕获事件(document原生事件捕获最先执行)

3 子元素阻止react事件冒泡

e.stopPropagation();

import React from "react";
 
class Test extends React.Component {
  parentRef;
  childRef;
  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 = (e) => {
    e.stopPropagation();
    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 Test;

执行顺序

e.stopPropagation()只能阻止react合成事件的冒泡和document原生事件冒泡,并不能阻止自己和父元素原生事件的冒泡。

e.nativeEvent.stopImmediatePropagation()只能阻止document原生事件冒泡。

e.preventDefault()和不执行一样

e.nativeEvent.stopPropagation()只能阻止document原生事件冒泡。

如果我们在子原生的原声事件里面阻止冒泡,都阻止了。

import React from "react";
 
class Test extends React.Component {
  parentRef;
  childRef;
  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", (e) => {
      e.stopPropagation();
      console.log(`子元素原生事件冒泡`);
    });
  }
  handleParentBubble = () => {
    console.log(`父元素React事件冒泡`);
  };
  handleChildBubble = (e) => {
    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 Test;

执行顺序

在子元素的原声事件里面,阻止了所有的冒泡。同时也阻止了react事件。

在父元素原生事件中阻止冒泡

import React from "react";
 
class Test extends React.Component {
  parentRef;
  childRef;
  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", (e) => {
      e.stopPropagation();
      console.log(`父元素原生事件冒泡`);
    });
    this.childRef.current.addEventListener(
      "click",
      () => {
        console.log(`子元素原生事件捕获`);
      },
      true
    );
    this.childRef.current.addEventListener("click", (e) => {
      console.log(`子元素原生事件冒泡`);
    });
  }
  handleParentBubble = () => {
    console.log(`父元素React事件冒泡`);
  };
  handleChildBubble = (e) => {
    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 Test;

执行顺序

父元素原生事件中阻止冒泡阻止了react事件

阻止document原生事件的冒泡并不会阻止了react事件

 document.addEventListener("click", (e) => {
      e.stopPropagation();
      console.log(`document原生事件冒泡`);
 });

结论

react捕获事件快于原生捕获事件的执行

react冒泡事件慢于原生冒泡事件的执行

原生冒泡事件会阻止react事件。

以上就是深入了解React中的合成事件的详细内容,更多关于React合成事件的资料请关注脚本之家其它相关文章!

相关文章

  • React+Antd+Redux实现待办事件的方法

    React+Antd+Redux实现待办事件的方法

    这篇文章主要介绍了React+Antd+Redux实现待办事件的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • React Native 集成 ArcGIS 地图的详细过程

    React Native 集成 ArcGIS 地图的详细过程

    ArcGIS官方提供了 JavaScript SDK,也提供了 ArcGIS-Runtime-SDK-iOS,但是并没有提供 React Native的版本,所以这里使用了 react-native-arcgis-mapview 库,本文给大家介绍React Native 集成 ArcGIS 地图的详细过程,感兴趣的朋友跟随小编一起看看吧
    2024-06-06
  • 基于React-Dropzone开发上传组件功能(实例演示)

    基于React-Dropzone开发上传组件功能(实例演示)

    这篇文章主要介绍了基于React-Dropzone开发上传组件,主要讲述的是在React-Flask框架上开发上传组件的技巧,需要的朋友可以参考下
    2021-08-08
  • 解决React报错Expected an assignment or function call and instead saw an expression

    解决React报错Expected an assignment or funct

    这篇文章主要为大家介绍了React报错Expected an assignment or function call and instead saw an expression解决方案详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • 详解React中组件之间通信的方式

    详解React中组件之间通信的方式

    这篇文章主要介绍了React中组件之间通信的方式,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-07-07
  • React Router6.x路由表封装的两种写法

    React Router6.x路由表封装的两种写法

    本文主要介绍了React Router6.x路由表封装的两种写法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-01-01
  • React Redux应用示例详解

    React Redux应用示例详解

    这篇文章主要介绍了如何在React中直接使用Redux,目前redux在react中使用是最多的,所以我们需要将之前编写的redux代码,融入到react当中去,本文给大家详细讲解,需要的朋友可以参考下
    2022-11-11
  • React中state属性和生命周期的使用

    React中state属性和生命周期的使用

    这篇文章主要介绍了React中state属性和生命周期的使用说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • React实现翻页时钟的代码示例

    React实现翻页时钟的代码示例

    本文给大家介绍了React实现翻页时钟的代码示例,翻页时钟把数字分为上下两部分,翻页效果的实现需要通过设置 position 把所有的数组放在同一个位置叠加起来,文中有详细的代码讲解,需要的朋友可以参考下
    2023-08-08
  • 解析react 函数组件输入卡顿问题 usecallback react.memo

    解析react 函数组件输入卡顿问题 usecallback react.memo

    useMemo是一个react hook,我们可以使用它在组件中包装函数。可以使用它来确保该函数中的值仅在依赖项之一发生变化时才重新计算,这篇文章主要介绍了react 函数组件输入卡顿问题 usecallback react.memo,需要的朋友可以参考下
    2022-07-07

最新评论