Implementation of front-end routing

Front-end routing and single-page pages

Routing means that as the browser address bar changes, the page displayed to the user is also different.
In traditional web pages, according to different addresses accessed by the user, the browser obtains the content of the corresponding page from the server and displays it to the user. This causes a lot of pressure on the server, and the user access speed is relatively slow. In this scenario, single-page applications appear.
A single-page application means that there is only one page, the user visits a website, and the server returns only one page. No matter the user changes the content of the browser address bar or jumps in the page, the server will not return to the new page again. Instead, the page changes are implemented through the corresponding js operations. The content of the address bar is changed, and different pages are displayed, which is achieved by front-end routing.

Implementation of front-end routing

Front-end routing is mainly implemented in two ways:

  1. location.hash+hashchange事件
  2. history.pushState () + popState case

hash+hashchange implementation

The advantage of this method is that it supports IE browser. Support for some early browsers is better.
Implementation principle:
location.hash always points to the content after # in the page url
When the url of the current page = 'www.baidu.com', you can enter the location.hash in the console of the browser to be empty, when the page points to url = 'www' .baidu.com/#/hello', location.hash = '#/hello'. By reading location.hash, you can know the location of the current page. The change of location.hash can be monitored through the hashchange event, so that the corresponding processing can be performed.
So how to trigger the change of the hash? There are mainly two methods here:

  1. Set a tag, href = '#/blue', when clicking on the tag, you can add '#/blue' to the back of the current url, trigger the hashchange at the same time, and then process it in the callback function.
  2. You can directly set location.hash = '#/blue' in js. At this time, the url will change and the hashchange event will also be triggered.
    The following is a general implementation of hash front-end routing:
function Router(){
  this.currentUrl='';
  this.routes={};
}
Router.prototype.route = function(path,callback){
  this.routes[path] = callback || function(){}
}
Router.prototype.refresh = function(){
  this.currentUrl = location.hash.slice(1) || '/';
  this.routes[this.currentUrl]();
}
Router.prototype.init = function(){
  window.addEventListener('load',this.refresh.bind(this),false);
  window.addEventListener('hashchange',this.refresh.bind(this),false);
  // console.log(location.hash)
  // if(location.hash.slice(1)!=='/')
  //     location.hash = '#/';
}

The above defines a Router object, which can be used in the instance like this:

var route = new Router();
route.init();
function changecolor(color){
  var body = document.getElementsByTagName('body')[0];
  body.style['background-color'] = color;
}
route.route('/',changecolor.bind(null,'skyblue'));
route.route('/blue',changecolor.bind(null,'blue'));
route.route('/green',changecolor.bind(null,'green'));
route.route('/color',function(){
  var p= document.getElementsByTagName('a');
  [].forEach.call(p,function(item){item.style['color'] = '#'+((~~(Math.random()*(1<<24))).toString(16));})
});

Create a new Router instance, initialize it, and then bind the url to the callback, so that the corresponding callback can be triggered when the hash changes. This method supports the forward and backward of the browser. It solves the problem after the front and back ends are separated very well. One disadvantage of this method is the existence of #, which makes some people feel uncomfortable, so html adds some APIs to the history, so as to realize front-end routing in a more elegant way.

history.pushState()+popstate

Like the previous method, pushState() modifies the address of the url, and popstate listens for changes in the address. The difference is that manually performing pushState() will not trigger the popstate event.
It can be understood like this:

  1. The user clicks a link, triggering ajax to get a new page or triggering some operations in js, changing the dom structure.
  2. We want to save the previous page, at this time we use pushState(data,null,url) to save the information of the previous page.
  3. When the user clicks forward or backward of the browser, the popstate event is triggered, the data can be read, and then the operation of the page or ajax can be used to obtain the data of the page, or the data in pushState() can be used to restore and update .

I wrote a demo myself for easy understanding. The links in the url are all prefixed with #/, mainly because if it is a relative path, the server side will directly jump to the corresponding web page. Whatever the relative url is, it will return the original page.

1.24 Update: The url directly uses relative paths here, which can realize forward and backward. The problem lies in the refresh. When the user refreshes, at this time, if the server does not process it, there will be no page displayed, and the server only needs to output the original page. It can perfectly solve the problem.

;(function(){
    var div1 = document.getElementById('div1');
    var a1 = document.getElementById('a1');
    var a2 = document.getElementById('a2');
    var count1 = 0;
  var count2 = 0;
  history.replaceState({count1:count1,count2:count2},null,'');//最开始的状态,采用replace直接替换
    a1.addEventListener('click',function(){
    count1++;
        history.pushState({count1:count1,count2:count2},null,'#/s'+count1);//之后的状态,需要进行保存
        a1.innerHTML = 's'+count1;
    })
    a2.addEventListener('click',function(){
    count2++;
        history.pushState({count1:count1,count2:count2},null,'#/k'+count2);//之后的状态,需要进行保存
        a2.innerHTML = 'k'+count2;
    })
    window.addEventListener('popstate',function(e){
    console.log(e.state);
    a1.innerHTML = 's'+e.state.count1;//监听popstate事件,对状态进行还原
      a2.innerHTML = 'k'+e.state.count2;
    })
})()

The immediate execution function is used to avoid polluting global variables. Clicking on the a1 and a2 elements will perform the pushState operation. When the forward and backward are performed, the popstate event will be triggered. By restoring the elements in this event, the elegant Solved the single page application forward and backward problem.

For the complete code see: code

For the demo page, see: demo

Summarize

When the user's operation modifies the DOM structure, and we hope that the user can go back to the previous step through the browser's forward operation, we need to use front-end routing.

The hash can be saved well, and it can also automatically save the dom structure of the current page. To support IE, the url of the page must start with #. The code is relatively complex.

And history is also a method, the idea is simple, more in line with the purpose of front-end routing, the code is simple, the url can be specified at will, if it is a pure relative path, it needs to be processed on the server side.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325030082&siteId=291194637