A detailed analysis of the core history library in React router

Source: Internet
Author: User
This article introduces the content of the react router in the core of the history of the Library of detailed analysis, there is a certain reference value, the need for a friend can refer to, I hope you have some help.

Objective

Using React to develop a slightly more complex application, React router is almost the only option for routing management. Although react router experienced 4 large versions of the update, the function is more and more rich, but no matter how changed, its core dependence on the history library has remained unchanged. Let's take a look at what features this library of 4k+ stars on GitHub actually provides.

HTML5 History Object

Talk to the history library, do you think this word is a bit familiar? Yes, the HTML5 specification also adds a new history object with the same name. Let's look at what this history object is used to solve.

In the era of jquery's reign, it was a popular way of page processing to request a page without refresh through Ajax, and the prototype of the SPA evolved at that time. In order to mark the changes in the page, it is convenient to display the correct page elements after the refresh, and the page is uniquely positioned by changing the hash value of the URL. But this poses another problem: users cannot use forward/backward to switch pages.

In order to solve this problem, the history object was born. When the URL or hash of the page changes, the browser will automatically push the new URL into the history object. A state array is maintained inside the history object to record the changes to the URL. When the browser makes a forward/backward operation, it actually invokes the corresponding method (/) of the History object and forward back takes out the corresponding state to switch the page.

In addition to manipulating the Url,history object, it also provides 2 ways to update the internal state without manipulating the URL, respectively pushState replaceState . Additional data can also be stored in the state and then onpopstate taken out of the event event.state . If you want to have a deeper understanding of the history object, you can refer here, and here.

Relationship between the history library and the HTML5 history object

We'll look back at the history library. It essentially does the following 4 things:

    1. Based on the concept of HTML5 history object, some functions have been expanded.

    2. Provides 3 types of history:browserhistory,hashhistory,memoryhistory, and maintains a unified API

    3. Supports the Publish/subscribe function, which can automatically trigger the subscription when history changes

    4. Provides useful functions such as jump intercept, jump confirmation and basename.

Compare the similarities and differences between the two APIs. The following are the history libraries:

Const HISTORY = {    length,        //property, number of state recorded in historical    action,        //property, action type location for current navigation    ,      / /attribute, location object, encapsulates pathname, search and hash properties    push,          //method, navigates to new route, and records replace in history    ,       //method, Replace the current record in the history of the routing information    go,            //method, forward or backward N records    GoBack,        //method, back    GoForward,     //method, forward    CanGo,         //method, can forward or backward n record    block,         //method, before jumping let the user determine whether to jump    listen         //method, subscribe to the history Change event  };

The following are the HTML5 history objects:

Const HISTORY = {    length,         //property, the number of state recorded in histories state    ,          //Properties, Pushstate, and Replacestate objects passed in    back,           //method, fallback    forward,        //method, Forward    go,             //method, forward or backward N records    pushstate,      //method, Navigate to the new route and record the    replacestate    //method in the history, replacing the routing information in the history with the current record}//subscribe to the historical Change event Window.onpopstate = function (event) {    ...}

As can be seen from the comparison, the relationship between the two is very close, the history library can be said to be a superset of the history object, is a more powerful history object.

Createhashhistory Source Code Analysis

Below, we take one of three types of history, Hashhistory, as an example, to analyze the source of the history of history, to see what it has done. Let's look at how it handles the hash change.

Construct Hashhistory Object Const Createhashhistory = (props = {}) + = {... const globalhistory = window.history; Referencing the HTML5 History object ...//Transitionmanager is responsible for controlling whether to jump, and the subscribers to be notified after the jump, the following will be discussed in detail const Transitionmanager = Createtra    Nsitionmanager (); ...//register subscriber of the history change callback Const LISTEN = Listener = {Const Unlisten = Transitionmanager.appendlistener (li        Stener);        Checkdomlisteners (1);            return () = {checkdomlisteners (-1);        Unlisten ();    };        };        Monitor Hashchange Event Const Checkdomlisteners = Delta = {Listenercount + = Delta;        if (Listenercount = = = 1) {Window.addeventlistener (hashchangeevent, Handlehashchange);        } else if (listenercount = = = 0) {Window.removeeventlistener (hashchangeevent, Handlehashchange);        }    };        Hashchange Event Callback Const Handlehashchange = () = {...//the location object used inside the construct, including properties such as pathname, search, and hash Const LOCATIOn = getdomlocation ();    .. handlepop (location);        };        Handle hash Change Logic Const HANDLEPOP = location + {... const action = "POP"; Show the user the information to confirm the jump (if any) and notify the Subscriber after confirmation.            If the user cancels the jump, it rolls back to the previous state Transitionmanager.confirmtransitionto (location, action, getuserconfirmation, OK + = {    if (OK) {setState ({action, location});             Notify Subscribers after confirmation} else {Revertpop (location);    Cancel to fall back to the previous State}});        };        Update the Action,location and length properties and notify subscribers of const SetState = Nextstate = {object.assign (history, Nextstate);        History.length = Globalhistory.length;    Transitionmanager.notifylisteners (History.location, history.action);    }; ...}

The above is to deal with the logic of the passive hash change, a short summary is: The subscription hash change event, to determine whether it is true to change, if necessary to update their own properties, notify Subscribers, do not need to change back to the previous state.

below to see what Transitionmanager did, focus on publish/subscribe related content, ignore the user confirm jump related content.

Const Createtransitionmanager = () = {    ...    List of internally maintained subscribers let    listeners = [];    Registered Subscriber    Const Appendlistener = fn + = {Let        isActive = true;        Const LISTENER = (... args) = = {            if (isActive) fn (... args);        };        Listeners.push (listener);        return () = {            isActive = false;            Listeners = Listeners.filter (item = Item!== listener);};    }    ; Notifies the subscriber    const Notifylisteners = (... args) = {        Listeners.foreach (listener = Listener (... args));    };    ...}

The code at a glance here is to maintain a list of subscribers and notify the relevant function when the hash is changed.

The above is the change of the hash when the passive update related content, and then see the active update related code, push as an example, replace similar.

Const PUSH = (path, state) = = {    ...    Const ACTION = "PUSH";    Const LOCATION = createlocation (path, undefined, undefined, history.location);    Transitionmanager.confirmtransitionto (location, action, getuserconfirmation, OK = = {if        (!ok)     //If canceled, does not jump            return;        ...        Pushhashpath (Encodedpath);        Replace the URL with a new hash        ...        SetState ({action, location});     Update the Action,location and length properties and notify Subscribers    });};/ /Replace with new hash to URL const Pushhashpath = path + (Window.location.hash = path);

The history library is actually implemented by manipulating the HTML5 history object while the browser is in the forward and backward operation.

Const Globalhistory = Window.history;const Go = n + = {    ...    Globalhistory.go (n);}; Const GOBACK = () + Go ( -1); const GoForward = () = () + go (1);

When called window.history.go , the hash changes to trigger the Hashchange event, and the history library then notifies the relevant subscriber of the change.

Summarize

This paper gives a more in-depth introduction to the react router core-dependent history library. From the new History object of HTML5, this paper contrasts its relationship with the history Library, and analyzes the implementation details of the code in detail with Hashhistory as an example.

Finally, let's review what the History Library has done:

    1. Based on the concept of HTML5 history object, some functions have been expanded.

    2. Provides 3 types of history:browserhistory,hashhistory,memoryhistory, and maintains a unified API

    3. Supports the Publish/subscribe function, which can automatically trigger the subscription when history changes

    4. Provides useful functions such as jump intercept, jump confirmation and basename.

Although the history Library is a core reliance of react router, it has no dependency on react itself. If you have a scene in your project that has a history of operations, you can also bring it into the project.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.