搜索

查看: 3035|回复: 11

[JavaScript] 深入了解React中的合成事件

[复制链接]
发表于 2023-5-4 11:49:50 | 显示全部楼层 |阅读模式
Editor 2023-5-4 11:49:50 3035 11 看全部
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 (
      
        
          事件处理测试
        
      
    );
  }
}

export default Test;
执行顺序

2023022010425523.png

2023022010425523.png


只留子元素修改代码
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 (
      
        事件处理测试
      
    );
    return (
      
        
          事件处理测试
        
      
    );
  }
}

export default Test;

2023022010425624.png

2023022010425624.png


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 (
      
        
          事件处理测试
        
      
    );
  }
}

export default Test;
执行顺序
e.stopPropagation()只能阻止react合成事件的冒泡和document原生事件冒泡,并不能阻止自己和父元素原生事件的冒泡。

2023022010425625.png

2023022010425625.png


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

2023022010425626.png

2023022010425626.png


e.preventDefault()和不执行一样

2023022010425627.png

2023022010425627.png


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

2023022010425628.png

2023022010425628.png


如果我们在子原生的原声事件里面阻止冒泡,都阻止了。
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 (
      
        
          事件处理测试
        
      
    );
  }
}

export default Test;
执行顺序

2023022010425729.png

2023022010425729.png


在子元素的原声事件里面,阻止了所有的冒泡。同时也阻止了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 (
      
        
          事件处理测试
        
      
    );
  }
}

export default Test;
执行顺序

2023022010425730.png

2023022010425730.png


父元素原生事件中阻止冒泡阻止了react事件
阻止document原生事件的冒泡并不会阻止了react事件
document.addEventListener("click", (e) => {
      e.stopPropagation();
      console.log(`document原生事件冒泡`);
});

2023022010425731.png

2023022010425731.png


结论
react捕获事件快于原生捕获事件的执行
react冒泡事件慢于原生冒泡事件的执行
原生冒泡事件会阻止react事件。
以上就是深入了解React中的合成事件的详细内容,更多关于React合成事件的资料请关注知鸟论坛其它相关文章!
回复

使用道具 举报

发表于 2023-6-28 17:25:00 | 显示全部楼层
123456825 2023-6-28 17:25:00 看全部
这个帖子不回对不起自己!我想我是一天也不能离开知鸟论坛
回复

使用道具 举报

发表于 2023-6-28 17:41:55 | 显示全部楼层
贺老师 2023-6-28 17:41:55 看全部
论坛不能没有像楼主这样的人才啊!我会一直支持知鸟论坛
回复

使用道具 举报

发表于 2023-6-28 23:14:05 | 显示全部楼层
向往草原403 2023-6-28 23:14:05 看全部
其实我一直觉得楼主的品味不错!呵呵!知鸟论坛太棒了!
回复

使用道具 举报

发表于 2023-6-29 13:59:39 | 显示全部楼层
心随674 2023-6-29 13:59:39 看全部
其实我一直觉得楼主的品味不错!呵呵!知鸟论坛太棒了!
回复

使用道具 举报

发表于 2023-6-29 18:53:04 | 显示全部楼层
丁侦球 2023-6-29 18:53:04 看全部
楼主发贴辛苦了,谢谢楼主分享!我觉得知鸟论坛是注册对了!
回复

使用道具 举报

发表于 2023-6-29 19:06:31 | 显示全部楼层
尘埃416 2023-6-29 19:06:31 看全部
其实我一直觉得楼主的品味不错!呵呵!知鸟论坛太棒了!
回复

使用道具 举报

发表于 2023-6-29 19:11:33 | 显示全部楼层
冀苍鸾 2023-6-29 19:11:33 看全部
楼主,大恩不言谢了!知鸟论坛是最棒的!
回复

使用道具 举报

发表于 2023-6-29 19:34:21 | 显示全部楼层
麻辣鸡翅 2023-6-29 19:34:21 看全部
楼主太厉害了!楼主,I*老*虎*U!我觉得知鸟论坛真是个好地方!
回复

使用道具 举报

发表于 2023-6-29 22:45:57 | 显示全部楼层
计划你大爷计j 2023-6-29 22:45:57 看全部
我看不错噢 谢谢楼主!知鸟论坛越来越好!
回复

使用道具 举报

  • 您可能感兴趣
点击右侧快捷回复 【请勿灌水】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则 返回列表

RSS订阅| SiteMap| 小黑屋| 知鸟论坛
联系邮箱E-mail:zniao@foxmail.com
快速回复 返回顶部 返回列表