JavaScript does not refresh the browser to achieve the forward and backward function

  • 2020-03-30 04:14:31
  • OfStack

Recently, I was learning backbone. to understand backbone. you need to understand spa, and to understand spa, you need to understand how a single-page application can change the url without refreshing the page.

For the first problem, the solution is relatively easy, as long as the cookie or localStorage is used to record the state of the application, read the state when the page refreshes, and then send the corresponding ajax request to change the page. However, the second problem is more troublesome. Let's talk about the solution of modern browsers first.

HTML5 solution

To see how HTML5 can go backwards and forwards, you need to look at the history object and the location object.

The history object

History object property

1. Length: returns the number of urls in the browser history list, plus 1 for each page the user visits in the current TAB. For privacy reasons, the specific content of the URL is not visible.
2. State: objects related to the current url can only be added or modified by pushState and replaceState. We can use it to store information about urls.

History object method

1. The history. The back ()

This method takes no arguments, and when triggered it returns to the previous page, which is equivalent to clicking the browser's back button.

2. The history. The forward ()

This method has no parameters, and when triggered it returns to the page that was viewed before the back, which is equivalent to clicking the browser's forward button.

3. The history. The go (number)

This method takes an argument of a plastic variable, history.go(-1) is equivalent to going back one page, history.go(1) is equivalent to going forward one page, and history.go(0) refreshes the current page.

4. History. PushState (state, the title, url)

The key to changing the url without refreshing the page is this method, which changes the location.href of the current page and modifies the current history.state object, increasing the history.length by 1. This method takes three parameters,

1. State: object related to the current url.
2. Title: the title of the page, but all browsers ignore it. To change the title, still use document.title.
3. Url: a url in the same domain as the current page, location.href will be changed to this value.

5. The history. ReplaceState (state, the title, url)

This method is the same as above, but it does not change the history.length, only when history.state and location.href are changed.

Note that the pushState and replaceState third parameters are not cross-domain and do not trigger the browser's popstate and onhashchange events (tested with chrome33).

Location object

In addition to clicking the forward/back button and the history event, you can also change the Url by modifying the location method and the location property:

Properties of the location object (read and write) :

1. Host: domain name + port number
2. The hostname: the domain name
3. Port: the port number
4. The protocol: the agreement
5. Href: full path
Origin: protocol + domain name + port
7. Hash: the URL(hash) at the beginning of the hashtag (#)
8. Pathname: document path + document name
9. The search: (the & # 63;) The rest

You can do this by changing location.href or location.hash.

Method of location object:

Assign: change the value of the url, and add the current url to the history.length will increase by 1. Location.assig (' #' + x) changes the url but does not refresh the page.
2. Reload the page.
3. Replace: change the value of the url, but keep the history.length the same. Use the same method as assign.

Popstate event

This event is triggered when the url changes, such as when the user clicks the forward/back button, history.go(n) (n does not equal 0), and location.hash = x(x does not equal the current location.hash). You can use it to listen for urls, to do all kinds of things.


    window.onpopstate = function(){
        //do sth
    }

Onhashchange event

Changing the hash value triggers the popstate event, which does not necessarily trigger the onhashchange event. Tested:

1. If the hash changes but the location.pathname remains the same, the onhashchange event will be triggered, such as history.pushstate (", ", '# ABC ');
2. If hash and location.pathname are changed together, it is not triggered, for example, history. PushState (", ", "a# ABC");

The way old browsers are written


var prevHash = window.location.hash;
var callback = function(){...}
window.setInterval(function() {
    if (window.location.hash != prevHash) {
        prevHash = window.location.hash;
        callback(prevHash);
    }
}, 100);

Of course, this is pretty lame, but if you don't consider changing the hash by clicking on the a tag with an id on the page, you can use design mode to elegantly monitor the url. The classic observer pattern, for example, USES a single class to change the hash, and then all the classes (observers) that listen for url changes subscribe to the (observed) class.


//The class that changes the url is
function UrlChanger() {
    var _this = this;
    this.observers = [];
    //Add observer
    this.addObserver = function(obj) {...}
    //Delete observer
    this.deleteObserver = function(obj) {...}
    //Notify the observer
    this._notifyObservers = function() {
        var length = _this.observers.length;
        console.log(length)
        for(var i = 0; i < length; i++) {
            _this.observers[i].update();
        }
    }
    //Change the url < br / >     this.changeUrl = function(hash) {
        window.location.hash = hash;
    _this._notifyObservers();
    }
}
//Listening class
function oneOfObservers() {
    var _this = this;
    this.update = function() {...}
}
//Implement < br / > var o1 = new UrlChanger();
var o2 = new oneOfObservers();
o1.addObserver(o2);
o1.changeUrl('fun/arg1/arg2/');
//o2 has do sth...


Related articles: