React events are not native events. React defines its own event system according to the W3C specification, which is called synthetic events.

The motivation of its custom event system mainly includes the following aspects:

(1) Smooth out the compatibility differences between different browsers. The primary motivation. (2) Event "synthesis", that is, event customization. Event composition can handle compatibility issues as well as custom events (such as the React onChange event). (3) Provide an abstract cross-platform event mechanism. Similar to VirtualDOM, which abstracts cross-platform rendering, synthetic Events provide an abstract cross-platform event mechanism. (4) More optimization can be done. For example, by using the event delegation mechanism, almost all events are triggered by the document instead of the DOM node itself, which simplifies the DOM event processing logic and reduces the memory overhead. React itself simulates a set of event bubbles. (5) It can interfere with event distribution. With the introduction of Fiber architecture in V16, React can optimize the user interaction experience by intervening in the distribution of events.Copy the code

Note: For example, some media events (such as onplay, onPause, etc.) in audio and video tags are not available in Document. These events can only be represented on these tags. But it is bound with the same dispatchEvent.

React The React event mechanism consists of two parts: event registration and event distribution. Let’s move on to the two specific processes:

Event registration

The React event registration process does two things: document registration and storing event callbacks.

(1) Document register in the componentDidMount (componentDidMount) process, on the Document according to the different event type register native event (using addEventListener as shown in the figure above), because the use of event delegate mechanism, so no matter what type of event, They all have the same callback function, dispatchEvent.

function TestComponent() {
  handleFatherClick=()=>{
		// ...
  }

  handleChildClick=()=>{
		// ...
  }

  return <div className="father" onClick={this.handleFatherClick}>
	<div className="child" onClick={this.handleChildClick}>child </div>
  </div>
}
Copy the code

The above code to register for two onclick event, they belong to the same event, register similar this document on the document. The addEventListener (‘ click ‘dispatchEvent), the same event no matter how many times will only leave a registered instance, This reduces memory overhead.

(2) Store event callbacks. As shown in the first figure, React stores events in an object (listenerBank). The object is first stored by event type, then generates a unique ID for each event as key, and stores callback functions as value.

Dispatching events

Event dispatch is also known as event triggering. React events only occur during the bubbling phase of the DOM event stream, because document is registered during the bubbling phase by default.

The general process is as follows: 1. Trigger the event and start the DOM event flow, which goes through three stages successively: event capture stage, target stage and event bubbling stage 2. Event bubbling on the document object ReactEventListener trigger uniform distribution function. The dispatchEvent 3. Find the ReactDOMComponent object 4 corresponding to the current node (that is, the event-triggering node) based on the nativeEvent. Event synthesis (1) Generate the corresponding composite object according to the current event type (2) encapsulate the native event object and bubble mechanism (3) find the current element and all its parents (4) find the event callback function in listenerBank and synthesize it into Events 5. 6. If bubbling is not prevented, the DOM event stream bubbling (document to window) will continue, otherwise the event firing will end

Note: The stopImmediatePropagation method used to prevent bubbling is as follows: StopPropagation can only prevent react composite events from bubblingevents. Stopdynamic Propagation can prevent native and React events

class TestComponent extends React.Component {

  componentDidMount() {
    this.parent.addEventListener('click', (e) => {
      console.log('dom parent');
    })
    this.child.addEventListener('click', (e) => {
      console.log('dom child');
    })
    document.addEventListener('click', (e) => {
      console.log('document');
    })
    document.body.addEventListener('click', (e) => {
      console.log('body');
    })
    window.addEventListener('click', (e) => {
      console.log('window');
    })
  }

  childClick = (e) => {
    console.log('react child');
  }

  parentClick = (e) => {
    console.log('react parent');
  }

  render() {
    return (
      <div class='parent' onClick={this.parentClick} ref={ref => this.parent = ref}>
        <div class='child' onClick={this.childClick} ref={ref => this.child = ref}>
          Click me!
        </div>
      </div>)
  }
}
Copy the code

When you click on Child div, the output looks like this:

React synthesized events are different from native DOM events: 1. Native events are bound to DOM elements, while synthesized events are bound to document objects. 2. Since a composite event fires in the event bubble phase, whereas a native event fires in the target phase, a native event always executes before a React composite event on the same element.