JSFiddle - React, Tailwind, and code Playground
by Alexander Maslakov
HTML
<ul>
<li><a href="#" id="link1">userView</a></li>
<li><a href="#" id="link2">authSignOut</a></li>
<li><a href="#/not_found_in_routes_list">notFound</a></li>
</ul>
<div id="result"></div>
JavaScript
class Router {
constructor (routes) {
this._routes = routes;
}
dispatch (uri) {
const normalizedUri = (uri ? uri: '/').replace(/^#/, '');
const routes = this._routes;
const routesNames = Object.keys(routes);
for (let i=0; i<routesNames.length; i++) {
const routeName = routesNames[i];
const routePattern = routes[routeName];
const normalizedRoutePattern = routePattern
.replace('\/', '\\/')
.replace(/\:[^\/]+/, () => '([^\/]+)');
const routeRegEx = new RegExp('^' + normalizedRoutePattern + '(?:\/|)$');
let matches = null;
if (matches = normalizedUri.match(routeRegEx)) {
const paramsHolders = routePattern.match(/\:([^\/]+)/g);
if (paramsHolders) {
const params = paramsHolders.reduce((accum, paramHolder, i) => {
accum[paramHolder.substring(1)] = matches[i + 1];
return accum;
}, {});
return {
uri: normalizedUri,
routeName,
params
};
}
return {
uri: normalizedUri,
routeName,
params: null
};
}
}
return {
uri: normalizedUri,
routeName: null,
params: null
};
}
uriFor (routeName, params={}) {
const routes = this._routes;
const routePattern = routes[routeName];
if (!routePattern) {
throw new Error(`Route with name '${routeName}' is not found.`);
}
const paramsHolders = routePattern.match(/\:([^\/]+)/g);
if (!paramsHolders) {
return routePattern;
}
let uri = routePattern;
for (let i=0; i<paramsHolders.length; i++) {
const holderName = paramsHolders[i].substring(1);
if (!params[holderName]) {
throw new Error(`Require param with name '${holderName}'.`);
}
uri = uri.replace(paramsHolders[i], params[holderName]);
}
return uri;
}
}
function onHashChange (router, handler, dispatchImmediately=true)...