一起学习网 一起学习网

深入了解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中的合成事件的详细内容