directory

  • The preface
  • The DOM event flow
    • Event capture phase, In target phase, event bubbling phase
    • The addEventListener method
  • React Event Overview
  • Event registration
    • The document registered on
    • Callback function storage
  • Dispatching events
  • summary
  • reference


1. Preface

React has its own system of events, called composite events. Why does React have a custom event system? How are React events registered and triggered? How are React events different from native DOM events? With these questions in mind, let’s explore how the React event mechanism works. For ease of understanding, this analysis will use diagrams instead of pasting the React source code whenever possible.


2. The DOM event stream

First, before getting into React events, it’s important to understand the DOM event flow, which consists of three phases: the event capture phase, the Target phase, and the event bubbling phase.

As early as 1988, the W3C began to develop THE DOM standard. The DOM standard can be divided into DOM1, DOM2 and DOM3 versions.

Starting from DOM2, DOM event propagation is divided into three stages: event capture stage, in target stage, and event bubbling stage.


(1) Event capture stage, in target stage and event bubbling stage

Sample code:

<html>
    <body>
        <div id="outer">
	    <p id="inner">Click me!</p>
	</div>
    </body>
</html>
Copy the code

In the code above, if you click on the

element, the DOM event flow looks like this:

(1) Event capture stage: The event object is propagated to the parent node of the target node through the ancestor Window of the target node.

(2) In the target stage: The event object reaches the event target node. If the event is prevented from bubbling, the event object will stop propagating after this phase is complete.

(3) Event bubbling stage: Event objects propagate from the parent of the target node in reverse order, from the parent of the target node to the Window.


(2) addEventListener method

The EVENT flow in the DOM includes both the event capture phase and the event bubbling phase, and as a developer, we can choose which phase the event handler is invoked.


The addEventListener() method is used to bind an event handler to a particular element. AddEventListener takes three arguments:

element.addEventListener(event, function.useCapture)
Copy the code


In addition, if an element is bound to the same event type more than once, duplicate instances are discarded. However, if the third parameter capture is not the same, it will not be discarded even if it is defined repeatedly.


3.React Event Overview

React defines its own system of events according to W3C specifications, which are 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 emulates an event bubbling mechanism)

(5) Can intervene in the distribution of events. With the introduction of Fiber architecture in V16, React can optimize the user interaction experience by intervening in the distribution of events.


Note: “almost” all events are represented in document, indicating exceptions such asaudio,videoSome tag media events (such as onplay, onPause, etc.) are not available in document. These events can only be represented by events on these tags, but they are still bound by a unified dispatchEvent function.


4. Event registration

The React event registration process does two things: registers the document and stores the event callback.


(1) Document registration

During the React component mount phase, according to the event type declared in the component (onclick, onchange, etc.), the document registers the event (using addEventListener) and specifies the unified callback function dispatchEvent. In other words, no matter what event is registered on document, there is a uniform callback function called dispatchEvent. Because of this event delegate mechanism, with the same callback function dispatchEvent, for the same event type, no matter how many times the document is registered, only one valid instance will be retained, which can reduce the memory overhead.


Sample code:

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

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

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

In the above code, the event type is onclick. Because React’s event delegate mechanism specifies the unified callback function dispatchEvent, only one click event will be retained on the document. Similar document. The addEventListener (‘ click ‘dispatchEvent), also can see from here the React of events are triggered in DOM event stream bubbling phase.


(2) Store event callback

React stores all the events in a component into a single object (listenerBank) in order to find the corresponding callback to execute when an event is triggered. For example, click events are stored uniformly in one object. Callback functions are stored in the form of key/value pairs. Key is the unique id of the component, and value corresponds to the callback function of the event.


The key steps for registering events with React are shown below:


5. Event distribution

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. The event is triggered and the FLOW of DOM events begins through three phases: the event capture phase, the Target phase, and the event bubbling phase
  2. When the event bubbles up to the Document, the unified event dispatch function is triggeredReactEventListener.dispatchEvent
  3. Find the ReactDOMComponent object corresponding to the current node (that is, the event-triggering node) based on the nativeEvent
  4. Composition of events
    1. Generates the corresponding composite object based on the current event type
    2. Encapsulates native event objects and bubbling mechanisms
    3. Finds the current element and all of its parents
    4. Find the event callback function in listenerBank and synthesize it into Events
  5. Batch execute the callback functions within synthetic events
  6. If bubbling is not prevented, the bubbling of the DOM event stream (document to Window) will continue, or the event firing will end

Note: In the figure above, the stopPropagation method should be called to stop bubbles. If stopPropagation is called to stop bubbles, other events of the same type registered on the Document will also be triggered to execute. However, event triggering on Windows is normally blocked. Understand the detailed differences between the two


Sample code:

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:

Child

-> parent

-> -> < HTML > -> Document -> window, so the output above is as expected.


6. Summary

React synthesized events differ from native DOM events:

(1) Events declared on the React component are not bound to the React component’s native DOM node.

React uses the event delegate mechanism to delegate almost all events on the Document node. Event objects are syntheticevents, not native event objects. However, the nativeEvent object is accessed through the nativeEvent property.

(3) Due to the event delegation mechanism of React, events on the native DOM node corresponding to the React component are always triggered before events on the React component.


Reference 7.

DOM0,DOM2,DOM3 level event model parsing in javascript

Event dispatch and DOM event flow

EventTarget. AddEventListener () – | MDN Web API interface reference

Synthetic events

React events and the future

React source Code series – Event mechanism

Learn how react events work