SoFunction
Updated on 2025-04-06

Detailed explanation of JavaScript to implement monitoring routing changes

There are two main ways to implement routing changes in the front-end. The biggest feature of these two methods is to realize the refresh-free function of URL switching.

  1. Change through hash, and use listening.
  2. Through history changes, js operations are used to load the page. However, history is not as simple as hash, because history changes, except for the browser's forward and backward (using the (), () and () methods to complete the backward and forward jumps in the user history.) operations will actively trigger the popstate event, pushState, and replaceState will not trigger the popstate event.

history

Let's learn about History

pushState() method

Three parameters are required: a state object, a title (currently ignored), and (optional) a URL. Let's explain the details of these three parameters:

State object — The state object state is a JavaScript object that creates a new history entry through pushState (). Whenever the user navigates to a new state, the popstate event is fired, and the state property of the event contains a copy of the state object of the history entry. A state object can be anything that can be serialized. The reason is that Firefox saves the state object on the user's disk for use when the user restarts the browser. We stipulate that the state object has a size limit of 640k after serializing the representation. If you pass a serialized state object greater than 640k to the pushState() method, the method will throw an exception. If you need more space, it is recommended to use sessionStorage and localStorage.

Title — Firefox currently ignores this parameter, but may be used in the future. Passing an empty string here should safely prevent future changes to this method. Alternatively, you can pass a short title for the jumped state.

URL — This parameter defines a new historical URL record. Note that the browser will not load the URL immediately after calling pushState(), but it may load the URL in some cases later (the resource will not be loaded, but we can change the view by listening to its changes. This becomes a way to implement single-page routing, which enables the page to be refreshed), such as when the user reopens the browser. The new URL does not have to be an absolute path. If the new URL is a relative path, it will be processed as relative to the current URL. The new URL must be the same as the current URL (same-origin policy), otherwise pushState() will throw an exception. This parameter is optional and defaults to the current URL.

In a sense, calling pushState() is similar to setting = "#foo", both of which create and activate new history on the current page. But pushState() has the following advantages:

The new URL can be any URL that has the same origin as the current URL. On the contrary, only when the hash is modified can the setting be the same document.
If you don't want to change the URL, you don't need to change it. Instead, set = "#foo"; to create a new history item when the current hash is not #foo.
You can associate any data with new history items. Based on hashing, all relevant data must be encoded into short strings.
If the title is then used by the browser, then this data can be used (the hash is not).

Note that pushState() will never trigger the hashchange event, even if the new URL is different from the old URL only hash.

pushState() usage scenario

History can implement refresh-free modification of URL or URL parameters

('', '', `${}${}type=a`);

replaceState() method

The use of () is very similar to (), the difference is that replaceState() is to modify the current history item rather than create a new one. Note that this does not prevent it from creating a new history item in the global browser history.
make

popstate event

Use to listen for return events

 = funcRef;

funcRef : (Event:{state:any})=>void

Whenever the history in the activated state changes, the popstate event will be triggered, triggering () on the corresponding window object. If the history entry currently in the active state is created by the () method or modified by the () method, the state property of the popstate event object contains a copy of the state object of the history entry.

**Notice:

  1. Calling() or () will not trigger the popstate event. The popstate event will only be triggered under certain behaviors of the browser, such as clicking the back or forward button (or calling the (), (), and () methods in JavaScript). In addition, the anchor point of the a tag will also trigger the event.
  2. When a web page is loading, each browser has different performance on whether the popstate event is triggered. Chrome and Safari will trigger the popstate event, while Firefox will not.

How to listen to pushState and replaceState?

We can implement it by subscribing and publishing mode ourselves: first use Dep and Watch, the subscription and publishing mode are actually a simple version that refers to the implementation method between dep and wantcher by referring to the vue source code.

class Dep {                  // Subscription pool    constructor(name){
         = new Date() // Here we simply use timestamps to make the subscription pool ID         = []       //The collection of subscribed objects under this event    }
    defined(){              // Add subscriber        (this);
    }
    notify() {              //Notify subscribers for changes        ((e, i) => {
            if(typeof  === 'function'){
                try {
                   (e)  //Trigger the subscriber update function                } catch(err){
                    (err)
                }
            }
        })
    }
    
}
 = null;

class Watch {
    constructor(name, fn){
         = name;       //The name of the subscription message         = new Date();   // Here we simply use timestamps as the subscriber's ID         = fn;     //Subscribe message sending changes -> callback function executed by subscriber    }
    add(dep) {                  //Put subscribers into the dep subscription pool       (this);
    }
    update() {                  //How to update subscribers        var cb = ; // Assign values ​​to not change this called in the function        cb();          
    }
}     

Re-history method and add addHistoryListener method

const addHistoryMethod= (function(){
 var historyDep = new Dep()// Create a subscription pool return function (name){
  if(name==='historyChange'){
   var event = new Watch(name,fn);
    = evnet;
   ();//Add subscribers    = null;
  }else if(name==='pushState'||name==='replaceState'){
   var method = history[name];
   return function(){
    (history,argumnets)
    ();
   }
  }
 }
})()
 = addHistoryMethod('historyChange')
 =  addHistoryMethod('pushState');
 =  addHistoryMethod('replaceState');

Package successfully, test usage example

('history',function(){
 ('Window history has changed')
})
('history',function(){
 ('The window history changes, I heard it too')// Multiple listening events can be bound ()
})
({foo:bar}, 'title', '/car')

Get the current status

When the page loads, there may be a non-null state object. This is possible, for example, if the page (via pushState() or replaceState() methods) sets the state object and the user restarts the browser. Then when the page reloads, the page will receive an onload event, but no popstate event. However, if you read the property, you will get the state object as you can get when popstate is triggered.

You can read the state object state of the current history item, without waiting for the popstate event, just use the attribute like this:

let currentState = ;

contrast

pushState replaceState
A new history will be created and activated on the current page. Clicking the return button will return to the previous url The current history will be modified, press the fallback button, and the modified URL will be skipped.

Summarize

History is a way to implement refresh-free routing, which is especially suitable for us to develop single pages to ensure stable and experientiality of the system. However, history does not listen to pushState and replaceState behaviors, but only listens to go, back, and forward behaviors. But we can use the subscription publishing mode, use Dep and Watch to reencapsulate pushState and replaceState events. After calling, the notify method will be automatically triggered, and an addHistoryListener method will be added to increase the listening callback (subscriber).

This is the article about detailed explanation of JavaScript's monitoring route changes. For more related JavaScript monitoring route changes, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!