preface

Before learning the vue-Router code, let’s take a quick look at front-end routing.

Front-end routing can be implemented in two ways:

  1. Hash routing
  2. The History of routing

Let’s take a look at how these two approaches work.

We’ll then use them to simply implement one of our own front-end routing.

The front-end routing

Hash routing

The URL hash begins with a # and is intended to serve as an anchor point to navigate to a specific area of the page. When the hash changes, the page does not refresh and the browser does not send a request to the server.

http://www.xxx.com/#/home
Copy the code

Also, when the hash changes, the corresponding HashChange event is triggered. Therefore, hashes are well suited for front-end routing. When the hash route is redirected, a hashChange callback is triggered, which can be used to update the page, thus achieving the effect of redirecting the page.

window.addEventListener('hashchange'.function () {
  console.log('render');
});
Copy the code

The History of routing

The HTML5 specification provides history.pushState and history.replacestate for routing control. With these two methods, you can change the URL without sending a request to the server. It also doesn’t have a # like hash, which is more aesthetically pleasing. However, the History route needs to be supported by the server, and all routes need to be redirected to the root page.

A change in the History route does not trigger an event, so we need to think about how to trigger the callback after the route is updated.

There are two ways to change the URL:

  1. Call history.pushState or history.replacestate;
  2. Click the browser forward and backward.

The first method encapsulates a method and calls the callback after calling pushState (replaceState).

function push (url) {
  window.history.pushState({}, null, url);
  handleHref();
}

function handleHref () {
  console.log('render');
}
Copy the code

Second, popState events are triggered when the browser moves forward and backward.

window.addEventListener('popstate', handleHref);
Copy the code

Routing implementation

We use the tag to switch the routing, and a

tag to load the corresponding page content for each route.

Referring to the vue-router call, we would call a router like this, passing in the route and the corresponding component as parameters:

const router = new Router([
  {
    path: '/'.component: 'home'
  },
  {
    path: '/book'.component: 'book'
  },
  {
    path: '/movie'.component: 'movie'}]);Copy the code

The array contains the contents of each route to be displayed, and we begin to implement the Router.

Hash Routing implementation

Hash routing tags need to be tagged with # :

<div>
  <a href="# /">home</a>
  <a href="#/book">book</a>
  <a href="#/movie">movie</a>
    
  <div id="content"></div>
</div>
Copy the code

The implementation of Router code is as follows:

class Router {
  constructor (options) {
    this.routes = {};
    
    this.init();
    
    // Iterate, binding view updates
    options.forEach(item= > {
      this.route(item.path, () => {
      	document.getElementById('content').innerHTML = item.component;
      });
    });
  }
  
  // Bind listener events
  init () {
    window.addEventListener('load'.this.updateView.bind(this), false);
    window.addEventListener('hashchange'.this.updateView.bind(this), false);
  }
  
  // Update attempts
  updateView () {
    const currentUrl = window.location.hash.slice(1) | |'/';
    this.routes[currentUrl] && this.routes[currentUrl]();
  }
  
  // Associate the route with the callback function
  route (path, cb) {
    this.routes[path] = cb; }}Copy the code

The results are as follows:

History routing implementation

The History route requires server support, which can be found here in the code reference.

<div>
  <a href="javascript:void(0);" data-href="/">home</a>
  <a href="javascript:void(0);" data-href="/book">book</a>
  <a href="javascript:void(0);" data-href="/movie">movie</a>
    
  <div id="content"></div>
</div>
Copy the code

The implementation of Router code is as follows:

class Router {
  constructor (options) {
    this.routes = {};

    this.init();
    this.bindEvent();

    // Iterate, binding view updates
    options.forEach(item= > {
      this.route(item.path, () => {
        document.getElementById('content').innerHTML = item.component;
      });
    });
  }

  // Bind the click event
  bindEvent () {
    const _this = this;
    const links = document.getElementsByTagName('a');

    [].forEach.call(links, link => {
      link.addEventListener('click'.function () {
        const url = this.getAttribute('data-href');
        _this.push(url);
      });
    });
  }

  // Bind listener events
  init () {
    window.addEventListener('load'.this.updateView.bind(this), false);
    window.addEventListener('popstate'.this.updateView.bind(this), false);
  }

  push (url) {
    window.history.pushState({}, null, url);
    this.updateView();
  }

  // Update attempts
  updateView () {
    const currentUrl = window.location.pathname || '/';
    this.routes[currentUrl] && this.routes[currentUrl]();
  }

  // Associate the route with the callback function
  route (path, cb) {
    this.routes[path] = cb; }}Copy the code

The results are as follows:

The last

There are two front-end routing implementations:

  1. Hash routing
  2. The History of routing

The principle is to change the URL at the same time do not refresh the page, do not send a request to the server, by listening to special events to update the page.

The above implementation of all source reference here.