Analysis of React Source Code (4): event system

April 15, 2023 1451hotness 0likes 0comments

in the previous three articles, we described the composition and life cycle of react components, and the mechanism of setState. This time let's talk about the handling of React events.

1. Native event system

We usually monitor the real DOM. For example, 🌰, we want to listen for the click event of the button, so we can bind the event and the corresponding callback function to the button DOM. Unfortunately, if the page is complex and the frequency of event processing is high, it is a test for the performance of the web page.

2.React event system

react's event handling, no matter how dazzling it is, will eventually return to the original event system, but its encapsulation is elegant. Let's go straight to the conclusion:

  • React implements the SyntheticEvent layer to handle events

What does

mean? In detail, React does not correspond events to Dom one by one like native events, but binds all events to the document of the web page, processes and distributes them through a unified event listener, finds the corresponding callback function and executes it. According to the official documentation, the event handler will pass an instance of SyntheticEvent, so let's take a look at SyntheticEvent.

3.SyntheticEvent

1. Event registration

as mentioned above, since React handles events uniformly, you must first need to register the event trigger function written by the programmer. So where is this process carried out? Because we are "binding" events to "component DOM", such as a click event:

<Component onClick={this.handleClick}/>
undefined

React has already started event handling through the _ updateDOMProperties method inside mountCompoent when the component is mounted. In this method, the enqueuePutListener method is executed to register the event:

The listenTo method calls the following two functions:

  • trapBubbledEvent
  • trapCapturedEvent

readers familiar with the native event system will know from the English translation that the two functions are used to deal with event capture and event bubbling. The specific processing logic is not analyzed, let's look directly inside these two functions:

the target in the above code, that is, document , also see the familiar document.addEventListener and document.removeEventListener . It is this unified event binding that reduces memory overhead.

2. Event Storage

the event callback function we wrote needs to be stored after it is registered so that it can be called back when triggered. The entry for storage is EventPluginHub.putListener function:

it can be seen that all callback functions are stored in listenerBank as a two-dimensional array, and are managed according to the component's corresponding key .

3. Event distribution

Now that we know about event registration and event storage, let's take a look at how React distributes events and finds the corresponding callback function and executes when the event is triggered. The distribution entry is located at handleTopLevelImpl of ReactDOMEventListener.js :

the above code clarifies the process: because the execution of the event callback function may lead to changes in the DOM structure, React first stores the current structure as an array and traverses the execution in turn. The _ handleTopLevel of the above function finally handles the callback function. Take a look at the source code:

A new role appears in the

code: EventPluginHub.extractEvents . Referring to the relevant materials, we know that the extractEvents method is used to synthesize events, that is, to synthesize instances of different cross-browser SyntheticEvent objects, such as SyntheticClickEvent , depending on the event type. And EventPluginHub is the tool plug-in used by React for compositing events:

you can see that React will use different functional plug-ins for different events, all of which are used internally through dependency injection. The process of synthesizing events in React is very tedious, but it can be summarized that the inner part of the extractEvents function is mainly through the switch function to distinguish the event types and call different plug-ins to deal with them, thus generating SyntheticEvent instances. Students who are interested can understand for themselves.

4. Event handling

The idea of

React handling events is similar to that of setState , both using batch processing. In the handleTopLevel method above, we see that the runEventQueueInBatch method is finally executed:

    //事件进入队列
    EventPluginHub.enqueueEvents(events);
    //...
    EventPluginHub.processEventQueue(false);
undefined

look at processEventQueue :

the above code iterates through the events in the queue and enters executeDispatchesAndReleaseSimulated :

event.constructor.release(event);
undefined

this line of code removes the React composition event release, reducing memory overhead. The core entry for event handling is executeDispatchesInOrder :

var dispatchListeners = event._dispatchListeners;
var dispatchInstances = event._dispatchInstances;

executeDispatch(event, simulated, dispatchListeners[i], dispatchInstances[i]);
undefined

these are the three important lines of code. dispatchListeners is the event callback function, and dispatchInstances is the corresponding component. Pass these parameters into executeDispatch :

function executeDispatch(event, simulated, listener, inst) {
    var type = event.type || 'unknown-event';
    ReactErrorUtils.invokeGuardedCallback(type, listener, event);
}
undefined

and invokeGuardedCallback is quite simple:

function invokeGuardedCallback(name, func, a) {
    func(a);
}
undefined

the func (a) above is actually listener (event) , and further up, it is dispatchListeners (dispatchInstances) , which explains why our React event callback function can get the native event.

4. Summary

React event system has done a lot of work to be compatible with various versions of browsers. We don't have to bother to study how these are implemented. Different from native events, React unifies rather than decentralized storage and management of events, generates synthetic events internally after capturing events to improve browser compatibility, and then destroys and releases memory after executing callback functions, thus greatly improving the response performance of web pages.

InterServer Web Hosting and VPS

Aaron

Hello, my name is Aaron and I am a freelance front-end developer

Comments