Escolar Documentos
Profissional Documentos
Cultura Documentos
@expalmer
A Javascript Enthusiast
Juntos Aprendemos Mais :)
January 4, 2016
Dividi o post em 2 partes, esse primeiro criando um router básico, e na sequencia um mais
completo.
Acredito que para quem é iniciante em Javascript o código seja um pouco hard, mas vou
tentar explicar com o máximo de detalhes possíveis, e se der tudo certo, você terá escrito
seu próprio router para usar em seus projetos.
Funcionamento do router
O router deve criar rotas, ou seja, informar um path e executar um callback quando esse
path for chamado.
https://expalmer.github.io/criando-seu-proprio-client-router-em-javascript-parte-1/ 1/14
29/05/2023, 19:23 Criando seu proprio Client Router em Javascript - Parte 1 - Palmer Oliveira. Juntos Aprendemos Mais!
Nosso router será uma função chamada micror (micro router...entendeu?) e seus
métodos serão:
micror('/', function(context) {
console.log('Home');
});
Aqui estamos chamando o path / que executará a rota que criamos acima.
micror.go('/');
Iniciando o router
Iniciar é opcional, mas iremos chamar essa função para pegar a url atual e
internamente executar o micror.go('url_atual') .
Nessa função podemos passar um objeto com 2 opções, que também são opcionais:
https://expalmer.github.io/criando-seu-proprio-client-router-em-javascript-parte-1/ 2/14
29/05/2023, 19:23 Criando seu proprio Client Router em Javascript - Parte 1 - Palmer Oliveira. Juntos Aprendemos Mais!
Mas existem situações que você precisa de um parâmetro, mas o mesmo é opcional, como
por exemplo em posts '/posts/:page/:order?' , note que nessa rota temos o :page
que é um parâmetro obrigatório, mas temos agora esse :order? onde temos um ? no
final, isso significa que o parâmetro é opcional.
micror('/post/:id', function(context) {
console.log(context.params.id);
});
micror('/posts/:page/:order?', function(ctx) {
console.log(context.params.page);
console.log(context.params.order);
});
Podemos também criar um rota universal usando * que será chamada com qualquer
path que colocarmos. Mas tem que se ligar na ordem onde a declaramos, pois se
colocarmos na frente de todas as outras rotas, somente ela executará e não cairá nas
demais. Por isso colocamos ela sempre no final para usar como um not found , ou seja,
se não der match em nenhuma rota, cai nela ;)
micror('/', function(ctx) {
console.log('Home');
});
micror('/about', function(ctx) {
console.log('Home');
});
micror('*', function(ctx) {
console.log('Rota Universal - Not Found');
});
https://expalmer.github.io/criando-seu-proprio-client-router-em-javascript-parte-1/ 3/14
29/05/2023, 19:23 Criando seu proprio Client Router em Javascript - Parte 1 - Palmer Oliveira. Juntos Aprendemos Mais!
Todo callback recebe uma instância do objeto Context , nele colocamos informações da
url como querystring e hash (quando houver). Mas nela também pegamos os
parâmetros (obrigatório e/ou opcional) informados na rota, e então colocamos no atributo
params .
micror('/posts/:page', function(context) {
console.log('page', context.params.page);
console.log('queryString', context.querystring);
console.log('hash', context.hash);
});
Alterando a Url
Cada vez que chamamos uma rota devemos alterar a url , e faremos isso com
history.replaceState.
Bom acho que é isso, vamos criar nosso router. De repente algumas coisas não ficaram
claras ainda, mas conforme criamos o código, as coisas vão clareando.
1) micror.js
Crie um arquivo chamado micror.js , todo código vai nele.
// nosso router :)
function micror(path, callback){
// criamos um objeto "route"
var route = {
path: path,
keys: []
};
// regexp
route.regexp = regexp(path,route.keys);
// armazenando as rotas
https://expalmer.github.io/criando-seu-proprio-client-router-em-javascript-parte-1/ 4/14
29/05/2023, 19:23 Criando seu proprio Client Router em Javascript - Parte 1 - Palmer Oliveira. Juntos Aprendemos Mais!
micror.callbacks.push(middleware(route, callback));
}
Cada vez que criamos uma rota, criamos um objeto chamado route que possui como
atributos ( path , keys , regexp ).
O atributo route.regexp chama a função regexp passando o path e suas keys que é
um array vazio. A função retorna uma expressão regular que será usada para comparar a
rota, e junto já extrai os parâmetros para colocar dentro de keys . Por exemplo, se damos
o path /posts/:page/:order? , é retornado
/^\/posts\/([^\/]+)(?:\/([^\/]+))?(?:\/(?=$))?$/i , e as keys ficarão assim
[ { name: 0 }, { name: 'page' }, { name: 'order' } ] .
A expressão regular acima diz que para fazer o match, precisa começar com /posts
seguido de qualquer coisa que não seja uma barra e contenha mais de um caracter,
seguido de opcionalmente qualquer coisa que não seja uma barra e contenha mais de um
caracter e opcionalemente termine com uma barra. Ufa...
Note que as keys já estão na ordem certinha dos parâmetros que informados na rota. Os
parâmetros obrigatório e/ou opcionais que usamos : e ? , são colocados os seus nomes
( { name: 'page' } ), nos parâmetros normais é colocado zero ( { name: 0 } ).
Mas para que isso tudo? Bom quando chamamos uma rota por exemplo
micror.go('/posts/10/asc') , já que temos nossas keys na ordem certa,
consiguimos juntar essas informações para colocar no context , saca só:
https://expalmer.github.io/criando-seu-proprio-client-router-em-javascript-parte-1/ 5/14
29/05/2023, 19:23 Criando seu proprio Client Router em Javascript - Parte 1 - Palmer Oliveira. Juntos Aprendemos Mais!
Esse é o truque.
2) regexp()
Essa é a função que faz tudo que falamos acima, dá uma conferida.
3) middleware()
Lá em cima fizemos isso
micror.callbacks.push(middleware(route, callback)); , aqui chamamos a
função middleware passando o objeto route e o callback . A função middleware
retorna uma outra função que espera um objeto context e uma função next .
Quando essa função for chamada, ela vai pegar o context passado e comparar com o
objeto route que o originou, comparando o route.regexp com o context.path. Se der
match nós preenchemos o atributo params do context com as keys do route conforme
falamos acima, e finalmente chamamos o callback passando o context.
Caso não dê match, é chamado a função next que irá verificar outra rota até dar match
ou acabar as rotas registradas.
https://expalmer.github.io/criando-seu-proprio-client-router-em-javascript-parte-1/ 6/14
29/05/2023, 19:23 Criando seu proprio Client Router em Javascript - Parte 1 - Palmer Oliveira. Juntos Aprendemos Mais!
}
}
4) fillParams
Essa função faz aquilo que falamos lá em cima, de juntar as keys e os parâmetros que
foram informados na url .
5) micror.go()
Aqui é que verificamos cada um dos callbacks das rotas que foram registrados.
Quando chamamos uma rota, primeiramente é criado uma instância do objeto Context ,
esse objeto pega o path passado e extrai várias informações importantes como:
path : Aqui é retirado a querystring e hash para poder fazer o match com o
route.regexp
querystring
hash
O Context possui também um método para fazer o replaceState , e já fazemos isso após
criá-lo.
https://expalmer.github.io/criando-seu-proprio-client-router-em-javascript-parte-1/ 7/14
29/05/2023, 19:23 Criando seu proprio Client Router em Javascript - Parte 1 - Palmer Oliveira. Juntos Aprendemos Mais!
Agora chamo a função callNextCallback que começa com o índice zero, e verifica se
possui uma função registrada em micror.callbacks , se sim, ele executa a função que é
aquela função middleware passando o context e ela própria callNextCallback. Lembra
que lá em cima a função next em middleware? Se não der match ele chama o next que é
na real nossa callNextCallback somando +1 no nosso índice, e segue adiante até
acabar as funções das rotas registrados...não é genial ?
micror.go = function(path) {
var context = new Context(path);
context.saveState();
var i = 0;
function callNextCallback() {
var callback = micror.callbacks[i++];
if(!callback) {
return console.log('route [', context.path, '] not found');
}
callback( context, callNextCallback );
}
callNextCallback();
};
6) micror.run()
Aqui é simples, inicializamos nossas options, depois pegamos a url atual e já
chamamos uma rota.
micror.run = function(opts) {
_base = opts && opts.base ? opts.base : '';
_hash = opts && opts.hash ? '#!' : false;
var url = location.pathname + location.search + location.hash;
url = _base ? url.replace(_base, '') : '';
if( _hash && ~location.hash.indexOf('#!') ) {
url = location.hash.substr(2) + location.search;
}
micror.go(url);
};
7) Context()
https://expalmer.github.io/criando-seu-proprio-client-router-em-javascript-parte-1/ 8/14
29/05/2023, 19:23 Criando seu proprio Client Router em Javascript - Parte 1 - Palmer Oliveira. Juntos Aprendemos Mais!
function Context(path) {
path = _base + (_hash ? '/#!' : '') + path.replace(_base,'');
path = path.length > 1 ? path.replace(/\/$/,'') : path;
this.fullPath = path;
path = _hash ? path.split('#!')[1] : (_base ? path.replace(_base,'') : pa
this.title = document.title;
this.params = {};
var h = path.split('#');
path = h[0];
this.hash = h[1] || '';
var q = path.split('?');
path = q[0];
this.querystring = q[1] || '';
this.path = path || '/';
}
Context.prototype.saveState = function() {
history.replaceState(this.state, this.title, this.fullPath );
};
Código completo
Segue o código completo agora.
micror.callbacks = [];
micror.go = function(path) {
var context = new Context(path);
context.saveState();
var i = 0;
function callNextCallback() {
var callback = micror.callbacks[i++];
https://expalmer.github.io/criando-seu-proprio-client-router-em-javascript-parte-1/ 9/14
29/05/2023, 19:23 Criando seu proprio Client Router em Javascript - Parte 1 - Palmer Oliveira. Juntos Aprendemos Mais!
if(!callback) {
return console.log('route [', context.path, '] not found');
}
callback( context, callNextCallback );
}
callNextCallback();
};
micror.run = function(opts) {
_base = opts && opts.base ? opts.base : '';
_hash = opts && opts.hash ? '#!' : false;
var url = location.pathname + location.search + location.hash;
url = _base ? url.replace(_base, '') : '';
if( _hash && ~location.hash.indexOf('#!') ) {
url = location.hash.substr(2) + location.search;
}
micror.go(url);
};
function Context(path) {
path = _base + (_hash ? '/#!' : '') + path.replace(_base,'');
path = path.length > 1 ? path.replace(/\/$/,'') : path;
this.fullPath = path;
path = _hash ? path.split('#!')[1] : (_base ? path.replace(_base,'') : pa
this.title = document.title;
this.params = {};
var h = path.split('#');
path = h[0];
this.hash = h[1] || '';
var q = path.split('?');
path = q[0];
this.querystring = q[1] || '';
this.path = path || '/';
}
Context.prototype.saveState = function() {
history.replaceState(this.state, this.title, this.fullPath );
};
https://expalmer.github.io/criando-seu-proprio-client-router-em-javascript-parte-1/ 10/14
29/05/2023, 19:23 Criando seu proprio Client Router em Javascript - Parte 1 - Palmer Oliveira. Juntos Aprendemos Mais!
Testando
Crie um arquivo chamado index.html , e coloque o código abaixo. Agora você precisa
levantar um servidor apache, node, python ... eu sempre recomendo o httpster.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>micro router</title>
<base href="/">
<style>
body {
background: #fff;
color: #666;
font-size: 1.1em;
}
a {
https://expalmer.github.io/criando-seu-proprio-client-router-em-javascript-parte-1/ 11/14
29/05/2023, 19:23 Criando seu proprio Client Router em Javascript - Parte 1 - Palmer Oliveira. Juntos Aprendemos Mais!
color: #444;
text-decoration: none;
text-shadow: -1px -1px 1px rgba(0,0,0,0.1);
}
a:hover {
color: #44666D;
}
h1 a {
display: inline-block;
color: #FC0E49;
}
.limiter {
margin: 0 auto;
max-width: 600px;
text-align: center;
}
ul li {
display: inline-block;
margin: 0 10px;
}
.display {
margin: 20px auto;
padding: 20px;
border-radius: 10px;
border: solid 1px #eee;
}
</style>
</head>
<body>
<div class="limiter">
<h1><a href="">micro router</a></h1>
<ul>
<li><a href="./">Home</a></li>
<li><a href="./about">About</a></li>
<li><a href="./post/42">Post</a></li>
<li><a href="./posts/1/asc">Posts</a></li>
<li><a href="./not-found">Not Found</a></li>
</ul>
<div class="display"></div>
</div>
<script src="/micror.js"></script>
<script>
micror('/', function(ctx) {
display.textContent = 'Rota Home';
});
https://expalmer.github.io/criando-seu-proprio-client-router-em-javascript-parte-1/ 12/14
29/05/2023, 19:23 Criando seu proprio Client Router em Javascript - Parte 1 - Palmer Oliveira. Juntos Aprendemos Mais!
micror('/about', function(ctx) {
display.textContent = 'Rota About';
});
micror('/post/:id', function(ctx) {
display.textContent = 'Rota Post com id = ' + ctx.params.id;
});
micror('/posts/:page/:order?', function(ctx) {
var html = 'Rota Posts com page = ' + ctx.params.page;
html += ' e order = ' + ctx.params.order || '';
display.textContent = html;
});
micror('*', function(ctx) {
display.textContent = 'PAGE NOT FOUND';
});
micror.run();
</script>
</body>
</html>
E o hash .
https://expalmer.github.io/criando-seu-proprio-client-router-em-javascript-parte-1/ 13/14
29/05/2023, 19:23 Criando seu proprio Client Router em Javascript - Parte 1 - Palmer Oliveira. Juntos Aprendemos Mais!
Post bem comprido :P, no próximo vamos colocar umas features bem legais.
2 Comments
Name
1 Share Best Ne
Alessandro Dias
7 years ago
Cara, gostei muito do tutorial e da sua explicação. Parabéns e obrigado por compartilhar :)
1 0 Reply • Share ›
Obrigado pelo feedback Alessandro, depois conta se conseguiu criar teu router.
0 0 Reply • Share ›
https://expalmer.github.io/criando-seu-proprio-client-router-em-javascript-parte-1/ 14/14