preface

Angular, React, and Vue are the three front-end frameworks. Their routing solutions Angular/Router, React – Router, and VUE-Router are all implemented based on front-end routing principles. Therefore, it is necessary to understand and master front-end routing principles. Once we understand how it works, we’ll be able to use it more easily in development.

What is routing?

The concept of routing originated from the server. In the past, when the front and back ends were not separated, the back end controlled routing. When receiving the HTTP request from the client, it would find the corresponding mapping function according to the corresponding URL requested, and then execute the function and send the return value of the function to the client. For the simplest static resource server, you can think of the mapping function of all urls as a file read operation. For dynamic resources, the mapping function may be a database read operation, some data processing, and so on. Then according to these read data, the server side will use the corresponding template to render the page, and then return the rendered page. Its advantages and disadvantages are obvious:

  • Benefits: Good security,SEOGood;
  • Disadvantages: increase the server pressure, is not conducive to user experience, code redundancy is not good maintenance;

It is because of the shortcomings of back-end routing that front-end routing has its own development space. For front-end routes, the route mapping function usually does some DOM show and hide operations. In this way, different page components are displayed when accessing different paths. Front-end routing mainly has the following two implementation schemes:

  • Hash
  • History

Of course, front-end routing has its drawbacks: using the browser’s forward and back keys to re-send requests to retrieve data does not make proper use of caching. In general, front-end routing is now the main way to implement routing. The three front-end frameworks Angular, React and Vue, and their routing solutions Angular/Router, React-Router and VUe-Router are all developed based on front-end routing. Therefore, it is necessary to understand and master front-end routing. In the following sections, two common front-end routing modes Hash and History are explained respectively.

Two implementations of front-end routing

2.1. Hash Mode

2.1.1, principle

Early implementations of front-end routing were based on location.hash. The implementation principle is simple: the value of location.hash is the content after the # in the URL. For example, here’s a website whose location.hash value is ‘#search’ :

https://www.word.com#search
Copy the code

In addition, hash has the following features:

  • URLhashValue is just a state on the client side, which means that when a request is made to the server side,hashParts will not be sent.
  • hashAny change in value adds a record to the browser’s access history. So we can control it through the browser’s back and forward buttonshashThe switch.
  • We can usehashchangeEvent to listenhashThe change.

There are two ways to trigger the hashchange. One is to use the a tag and set the href attribute. When the user clicks on the tag, the URL will change and the hashchange event will be triggered:

<a href="#search">search</a>
Copy the code

Alternatively, you can assign to loaction.hash directly in JavaScript to change the URL and trigger the hashchange event:

location.hash="#search"
Copy the code

The following implementation is implemented in the second way.

2.1.2, implementation,

Let’s start by defining a parent class BaseRouter that implements some common methods for Hash and History routes.

export class BaseRouter {
  // list indicates the routing table
  constructor(list) {
    this.list = list;
  }
  // page rendering function
  render(state) {
    let ele = this.list.find(ele= > ele.path === state);
    ele = ele ? ele : this.list.find(ele= > ele.path === The '*'); ELEMENT.innerText = ele.component; }}Copy the code

We have simply implemented the push function and go forward/backward function. The annotations of relevant codes have been marked, which are easy to understand and will not be introduced one by one. Please refer to the following:

export class HashRouter extends BaseRouter {
  constructor(list) {
    super(list);
    this.handler();
    // Listen for the hashchange event
    window.addEventListener('hashchange', e => {
      this.handler();
    });
  }
  // Re-render the page when the hash changes
  handler() {
    this.render(this.getState());
  }
  // Get the hash value
  getState() {
    const hash = window.location.hash;
    return hash ? hash.slice(1) : '/';
  }
  // Push a new page
  push(path) {
    window.location.hash = path;
  }
  // Get the default page URL
  getUrl(path) {
    const href = window.location.href;
    const i = href.indexOf(The '#');
    const base = i >= 0 ? href.slice(0, i) : href;
    return base +The '#'+ path;
  }
  // Replace the page
  replace(path) {
    window.location.replace(this.getUrl(path));
  }
  // Scan history forward or backward
  go(n) {
    window.history.go(n); }}Copy the code

2.1.3 Effect drawing

The Hash route implementation example is as follows:

2.2. History Mode

2.2.1, principle

The previous hash is also a good one, but it doesn’t look pretty when you use it. So in HTML5, there’s a History API to implement URL changes. The two main apis are history.pushstate () and history.repalcestate (). Both apis allow you to manipulate the browser’s history without refreshing it. The only difference is that the former is to add a history, while the latter is to replace the current history directly, as shown below:

window.history.pushState(null.null, path);
window.history.replaceState(null.null, path);
Copy the code

In addition, history has the following features:

  • pushStaterepalceStateThe title of the (title) : The general browser will ignore, the best passnull
  • We can usepopstateEvent to listenurlThe change of the;
  • history.pushState()history.replaceState()Not triggerpopstateEvent, in which case we need to manually trigger the page rendering;

2.2.2, implementation,

We have also simply implemented the push function and go forward/backward function. The annotations of relevant codes have been marked, which are easy to understand and will not be introduced one by one. Please refer to the following:

export class HistoryRouter extends BaseRouter {
  constructor(list) {
    super(list);
    this.handler();
    // Listen for popState events
    window.addEventListener('popstate', e => {
      console.log('Trigger popState... ');
      this.handler();
    });
  }
  // Render the page
  handler() {
    this.render(this.getState());
  }
  / / get the url
  getState() {
    const path = window.location.pathname;
    return path ? path : '/';
  }
  / / push page
  push(path) {
    history.pushState(null.null, path);
    this.handler();
  }
  / / the replace page
  replace(path) {
    history.replaceState(null.null, path);
    this.handler();
  }
   // Scan history forward or backward
  go(n) {
    window.history.go(n); }}Copy the code

2.2.3 Effect drawing

An example of routing implementation in History mode looks like this:

2.3 Comparison of the two routing modes

Contrast point Hash pattern The History mode
Beautiful sex With the # character, ugly Concise and beautiful
compatibility >= Ie 8, other major browsers >= Ie 10, other major browsers
practical No changes to the server are required The server needs to coordinate the route Settings

Third, summary

In this article, we briefly introduced the routing, the origin of front-end routing, and analyzed the principle and simple function implementation of two front-end routing modes: Hash mode and History mode. The code implementation of the examples in this article has been posted on Github: github.com/fengshi123/… . In this article, you can read the source code of vue-Router and React-Router based on the principle of front-end routing.

The github address is github.com/fengshi123/… If you like it or are inspired by it, please help to give it a star ~, which is also an encouragement to the author.

reference

1, the introduction to the front-end routing: www.jianshu.com/p/d2aa8fb95…

2, the front-end routing: segmentfault.com/a/119000001…