Module: router

This is a very simple routing class that listens to location hash changes and clicks on links to registered routes.

You have to explicitly define the routes that you wish to use, so we don't clash (too much) with deep-linking to named anchors on your page. And also because it enables you to handle different routes with different functions.

The biggest benefit of using this router is that you can navigate your single page app and still have a proper history. So forward and back buttons work, you can refresh and deep-link to a specific page, those kinds of things.

Create and install a router object:

import Router from './router.js';
const router = new Router().install();

Then, add routes. Either individually, maybe programmatically:

router.addRoute('welcome', navigationFunc);

Or multiple routes at once, configuration style:

router.addRoutes({
  router:   navigationFunc,
  activate: navigationFunc
});

If, like in these examples, all routes lead to the same function, you can declare them in one go:

router.addRoutes([ 'click',
                   'dragdrop' ], navigationFunc);

You then have to implement your own navigation or rendering functions. Maybe each page has a different function. In our case, we use this quick and dirty navigation solution: hide the active .page and show the one we requested.

function navigationFunc(route) {
  document.querySelector('.page.active').classList.remove('active');
  document.getElementById(route).classList.add('active');
  window.scrollTo(0,0);
};

If you like, you can pass any parameters that you would use with addRoutes to the constructor too:

new Router(
  [
    'welcome',
    'router',
    'energize',
    'click',
    'dragdrop'
  ],
  route => {
    document.querySelector('.page.active').classList.remove('active');
    document.querySelector(`#${route}`).classList.add('active');
    window.scrollTo(0,0);
  }
).install();

This is equivalent to:

new Router()
  .install()
  .addRoutes(
    [
      'welcome',
      'router',
      'energize',
      'click',
      'dragdrop'
    ],
    route => {
      document.querySelector('.page.active').classList.remove('active');
      document.querySelector(`#${route}`).classList.add('active');
      window.scrollTo(0,0);
    }
  );

Now all that's left to do is add some links with routing-power:

<nav>
  <ul>
    <li><a href="#welcome">Welcome!</a></li>
    <li><a href="#router">Router</a></li>
    <li><a href="#energize">Energize</a></li>
    <li><a href="#click">Click</a></li>
    <li><a href="#dragdrop">Drag & Drop</a></li>
  </ul>
</nav>

Advanced use

Regular expressions

If your routing needs are more complicated than string → function you can use regular expressions instead of strings. The navigation function gets called with three parameters: the matched route (either the string or the regular expression), the regular expression matches if any, and the original event that triggered the call to the navigation function:

router.addRoute(/admin\/users\/(\d+)/, (route, matches, e) => {
  console.log('This function was called because the location hash matched', route);
  console.log('We\'re interested in user number', matches[1]);
  console.log('This was the original navigation event:', e);
});

Nested routers

For readability or for nested components, you can nest router instances. This can be done in two ways: either by registering a route that leads to a router instance:

new Router()
  .install()
  .addRoutes({
    public: new Router({
      login:  loginFunc,
      logout: logoutFunc
    })
  });
<a href="#public/login">Click here to log in</a>

...or by calling route on the nested router:

const privateRouter = new Router({
  dashboard: dashboardFunc,
  users:     usersFunc
});

new Router()
  .install()
  .addRoute(/private\/(.*)/, (route, matches, evnt) => {
    if (!loggedIn) {
      window.location.hash = 'public/login';
      return;
    }

    privateRouter.route(matches[1], evnt);
  });
<a href="#private/dashboard">Go to your dashboard</a>

Please note that the router that you call the install function on is the one that will be the root router. This router binds itself to the right events.

Source: