React prevent event bubbling in nested components on click

前端 未结 8 1465
隐瞒了意图╮
隐瞒了意图╮ 2020-11-27 02:41

Here\'s a basic component. Both the

    and
  • have onClick functions. I want only the onClick on the
  • to fir
相关标签:
8条回答
  • 2020-11-27 03:19

    I had the same issue. I found stopPropagation did work. I would split the list item into a separate component, as so:

    class List extends React.Component {
      handleClick = e => {
        // do something
      }
    
      render() {
        return (
          <ul onClick={this.handleClick}>
            <ListItem onClick={this.handleClick}>Item</ListItem> 
          </ul>
        )
      }
    }
    
    class ListItem extends React.Component {
      handleClick = e => {
        e.stopPropagation();  //  <------ Here is the magic
        this.props.onClick();
      }
    
      render() {
        return (
          <li onClick={this.handleClick}>
            {this.props.children}
          </li>       
        )
      }
    }
    
    0 讨论(0)
  • 2020-11-27 03:25

    On the order of DOM events: CAPTURING vs BUBBLING

    There are two stages for how events propagate. These are called "capturing" and "bubbling".

                   | |                                   / \
    ---------------| |-----------------   ---------------| |-----------------
    | element1     | |                |   | element1     | |                |
    |   -----------| |-----------     |   |   -----------| |-----------     |
    |   |element2  \ /          |     |   |   |element2  | |          |     |
    |   -------------------------     |   |   -------------------------     |
    |        Event CAPTURING          |   |        Event BUBBLING           |
    -----------------------------------   -----------------------------------
    

    The capturing stage happen first, and are then followed by the bubbling stage. When you register an event using the regular DOM api, the events will be part of the bubbling stage by default, but this can be specified upon event creation

    // CAPTURING event
    button.addEventListener('click', handleClick, true)
    
    // BUBBLING events
    button.addEventListener('click', handleClick, false)
    button.addEventListener('click', handleClick)
    

    In React, bubbling events are also what you use by default.

    // handleClick is a BUBBLING (synthetic) event
    <button onClick={handleClick}></button>
    
    // handleClick is a CAPTURING (synthetic) event
    <button onClickCapture={handleClick}></button>
    

    Let's take a look inside our handleClick callback (React):

    function handleClick(e) {
      // This will prevent any synthetic events from firing after this one
      e.stopPropagation()
    }
    
    function handleClick(e) {
      // This will set e.defaultPrevented to true
      // (for all synthetic events firing after this one)
      e.preventDefault()  
    }
    

    An alternative that I haven't seen mentioned here

    If you call e.preventDefault() in all of your events, you can check if an event has already been handled, and prevent it from being handled again:

    handleEvent(e) {
      if (e.defaultPrevented) return  // Exits here if event has been handled
      e.preventDefault()
    
      // Perform whatever you need to here.
    }
    

    For the difference between synthetic events and native events, see the React documentation: https://reactjs.org/docs/events.html

    0 讨论(0)
提交回复
热议问题