Explanation of React Bubble and Prevent Bubble Application

  • 2021-08-06 20:37:14
  • OfStack

There are three kinds of events to prevent bubbling:

1: Prevent composite events from bubbling to events on the outermost document, using e. nativeEvent. stopImmediatePropagation ();

2: Compose bubbles between events, using e. stopPropagation ();

3: Prevent composite events from bubbling to other native events on document, which need to be judged by e. target. The example code is as follows.


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)}> Update </a>
</div>
    )
  }

componentDidMount() {
document.body.addEventListener('click',e=>{
//  Pass e.target Judge to prevent bubbling 
      if(e.target&&e.target.matches('a')){
return;
      }
console.log('body');
    })
  }
}

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

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

Demand

Recently, when writing the project of react, I need to write a custom menu by hand, which is different from menu of antd. After clicking the Level 1 menu, I need to pop up a similar Drawer to show Level 2 and Level 3 menus, and the menu style is customized, all of which are displayed in an Drawer.

Difficulties

The difficulty lies in the fact that Drawer pops up when clicking the level 1 menu, and dom and Drawer except Drawer and level 1 menu items are put away.

Problem

At first glance, I think it is to add a click event monitor to document, and add bubbling prevention to Drawer and level 1 menu. This is true, and it is found in the later implementation:
In order to improve performance, react has its own set of event handling mechanism, which is equivalent to handling events globally, that is to say, the listening function is not bound to Dom. Therefore, if the event that prevents react bubbles e. stopPropagation (), it will not bubble the native event, which shows that clicking Drawer will also fold Drawer;; If the native event bubbling e. nativeEvent. stopPropagation () is disabled, the listening function of React cannot be called, which shows that if you click dom other than Drawer, Drawer will not be put away. These are not what we want.

Solutions

The correct gesture should be to determine whether the event. target object is the target object or contains or contains the target object, so as to decide whether to trigger the event


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

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

 hideDrawer = e => {
  const { closeDrawer } = this.props;
  //  Find something that doesn't need to be closed dom 1 Level menu 
  const tabContent = document.querySelectorAll('.ant-menu-submenu-vertical');
  //  Find something that doesn't need to be closed dom   Drawer
  const drawerContent = document.querySelector('#menuDrawer');
  //  Determine the currently clicked dom Object is contained in the target dom Medium 
  const isHave = Array.from(tabContent).some(item => item.contains(e.target));
  //  Close if not included Drawer  Include other business logic 
  if (tabContent !== null && !(isHave || drawerContent.contains(e.target))) {
   closeDrawer();
  }
 };


Related articles: