React冒泡和阻止冒泡的应用详解

阻止事件冒泡分三种:

1:阻止合成事件往最外层document上的事件冒泡,用e.nativeEvent.stopImmediatePropagation();

2: 合成事件间的冒泡,使用 e.stopPropagation();

3:阻止合成事件,往处理document上的其他原生事件冒泡,需要通过e.target来判断,示例代码如下。

import React,{ Component } from 'react';
import ReactDOM,{findDOMNode} from 'react-dom';

class Counter extends Component{
constructor(props){
super(props);

this.state = {
count:0,
    }
  }

handleClick(e){
this.setState({count:++this.state.count});
  }
render(){
return(
<div ref="test">
<p>{this.state.count}</p>
<a ref="update" onClick={(e)=>this.handleClick(e)}>更新</a>
</div>
    )
  }

componentDidMount() {
document.body.addEventListener('click',e=>{
// 通过e.target判断阻止冒泡
      if(e.target&&e.target.matches('a')){
return;
      }
console.log('body');
    })
  }
}

var div1 = document.getElementById('content');

ReactDOM.render(<Counter/>,div1,()=>{});

需求

最近在写react的项目,需要手写一个自定义的菜单,和antd的menu不同,需要点击一级菜单后弹出类似一个Drawer展示二级和三级菜单,且菜单样式自定义,都在一个Drawer里展示。

难点

其中难点在于点击一级菜单时弹出Drawer,点击除Drawer和一级菜单项之外的dom,Drawer收起。

问题

乍一想就是给document添加一个点击事件监听,给Drawer和一级菜单添加阻止冒泡,思路确实如此,后面实现中发现:
react为提高性能,有自己的一套事件处理机制,相当于将事件代理到全局进行处理,也就是说监听函数并未绑定到Dom上。 因此阻止react的事件冒泡e.stopPropagation(),就不发阻止原生事件的冒泡,表现为点击Drawer也会收起Drawer;禁用原生事件冒泡e.nativeEvent.stopPropagation(),React的监听函数就调用不到,表现为点击Drawer以外dom,Drawer不会收起。这些都不是我们想要的。

解决方案

正确的姿势应该是判断event.target对象是否是目标对象或包含目标对象或被包含目标对象,以此来决定是否触发事件

 componentDidMount() {
  document.addEventListener('click', this.hideDrawer);
 }

 componentWillUnmount() {
  document.removeEventListener('click', this.hideDrawer);
 }

 hideDrawer = e => {
  const { closeDrawer } = this.props;
  // 找到不需要关闭的dom 一级菜单
  const tabContent = document.querySelectorAll('.ant-menu-submenu-vertical');
  // 找到不需要关闭的dom   Drawer
  const drawerContent = document.querySelector('#menuDrawer');
  // 判断当前点击的dom对象有没有包含在目标dom中
  const isHave = Array.from(tabContent).some(item => item.contains(e.target));
  // 不包含则关闭Drawer 包含就走其他的业务逻辑了
  if (tabContent !== null && !(isHave || drawerContent.contains(e.target))) {
   closeDrawer();
  }
 };

到此这篇关于React冒泡和阻止冒泡的应用详解的文章就介绍到这了,更多相关React冒泡和阻止冒泡内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

时间: 2020-08-18

React中阻止事件冒泡的问题详析

前言 最近在研究react.redux等,网上找了很久都没有完整的答案,索性自己整理下,这篇文章就来给大家介绍了关于React阻止事件冒泡的相关内容,下面话不多说了,来一起看看详细的介绍吧 在正式开始前,先来看看 JS 中事件的触发与事件处理器的执行. JS 中事件的监听与处理 事件捕获与冒泡 DOM 事件会先后经历 捕获 与 冒泡 两个阶段.捕获即事件沿着 DOM 树由上往下传递,到达触发事件的元素后,开始由下往上冒泡. IE9 及之前的版本只支持冒泡 |  A  --------------

JQuery中阻止事件冒泡几种方式及其区别介绍

JQuery 提供了两种方式来阻止事件冒泡. 方式一:event.stopPropagation(); 复制代码 代码如下: $("#div1").mousedown(function(event){ event.stopPropagation(); }); 方式二:return false; 复制代码 代码如下: $("#div1").mousedown(function(event){ return false; }); 但是这两种方式是有区别的.return

JS阻止事件冒泡的方法详解

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default5.aspx.cs"Inherits="Default5"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/

JavaScript中的事件与异常捕获详析

事件处理 [onClick]单击事件.[onMouseOver]鼠标经过事件.[onMouseOut]鼠标移出事件.[onChange]文本内容改变事件.[onSelect]文本被框选事件.[onFoucus]得到光标事件.[onBlur]光标失去事件.[onLoad]网页加载事件(在body标签中添加).[onUnload]网页关闭事件(在body标签中添加或者使用window.onload=function(){} ) 事件注册及监听 1. DOM0级事件处理 在标签中添加onClick或其

浅谈jQuery 中的事件冒泡和阻止默认行为

1.事件冒泡 <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+reque

在点击div中的p时,如何阻止事件冒泡

今天整理笔记,发现在学习javaScript的过程中,遇到过一个在当时看来很棘手的问题,现在特地总结一下,也希望能帮助到曾像我一样迷惘的初学者. 我还是以一个案例来说明问题,html代码如下: <div onclick="show('a')"> <p onclick="show('b')"></p> </div> css代码如下: div{ width:500px; height:500px; background:r

js阻止冒泡及jquery阻止事件冒泡示例介绍

js阻止冒泡 在阻止冒泡的过程中,W3C和IE采用的不同的方法,那么我们必须做以下兼容. 复制代码 代码如下: function stopPro(evt){ var e = evt || window.event; //returnValue如果设置了该属性,它的值比事件句柄的返回值优先级高.把这个属性设置为 fasle, //可以取消发生事件的源元素的默认动作. //window.event?e.returnValue = false:e.preventDefault(); window.ev

JS阻止事件冒泡行为和闭包的方法

阻止事件冒泡行为,要是不阻止的话,点击div的时候也会同时触发body事件 html代码 <body onclick='load()'> <div onclick='cli()'> click this </div> </body> css代码 div{ width:200px; height:200px; border:1px red solid; } js代码 function load(){ console.log('body') } function

javascript阻止事件冒泡和浏览器的默认行为

1.阻止事件冒泡,使成为捕获型事件触发机制. function stopBubble(e) { //如果提供了事件对象,则这是一个非IE浏览器 if ( e && e.stopPropagation ) //因此它支持W3C的stopPropagation()方法 e.stopPropagation(); else //否则,我们需要使用IE的方式来取消事件冒泡 window.event.cancelBubble = true; } 2.当按键后,不希望按键继续传递给如HTML文本框对象时

Jquery阻止事件冒泡 event.stopPropagation

描述: 防止事件冒泡到DOM树上,也就是不触发的任何前辈元素上的事件处理函数. version added: 1.0event.stopPropagation() 我们可以用 event.isPropagationStopped() 来确定这个方法是否(在那个事件对象上)调用过了. 这个方法对 trigger() 来自定义的事件同样有效. 注意,这不会阻止同一个元素上的其它事件处理函数的运行. Additional Notes: 自从.live()方法处理事件一旦传播到文档的顶部,live事件是