Tratamento de Caminhos (Path Handling)
m.route
e m.request
utilizam o conceito de caminho (path). Isso é usado para gerar a URL para a qual você roteia ou faz a requisição.
Tipos de Caminho (Path types)
Existem dois tipos principais de caminhos: caminhos diretos (raw paths) e caminhos com parâmetros.
- Caminhos diretos são strings usadas diretamente como URLs. Nenhuma substituição ou divisão é realizada. A string é normalizada com todos os parâmetros anexados ao final.
- Caminhos com parâmetros permitem inserir valores nos caminhos, com escape automático por padrão para conveniência e segurança contra injeção de URL.
Para m.request
, os caminhos podem ser praticamente qualquer URL. Para rotas, eles devem ser caminhos absolutos de URL sem protocolos ou domínios.
Parâmetros de Rota (Path parameters)
Os parâmetros de rota são simples e se apresentam em duas formas:
:foo
- Insere o valor deparams.foo
na URL, aplicando escape antes.:foo...
- Insere o valor deparams.foo
diretamente na URL, sem aplicar escape.
O objeto params
é o objeto params
passado para m.route.set(path, params)
ou m.request({url, params})
.
Ao definir rotas com m.route(root, defaultRoute, routes)
, você pode usar esses parâmetros para extrair valores das rotas. O funcionamento é similar à geração de caminhos, mas na direção oposta.
// Editar um único item
m.route(document.body, '/edit/1', {
'/edit/:id': {
view: function () {
return [m(Menu), m('h1', 'Editing user ' + m.route.param('id'))];
},
},
});
// Editar um item identificado por caminho
m.route(document.body, '/edit/pictures/image.jpg', {
'/edit/:file...': {
view: function () {
return [m(Menu), m('h1', 'Editing file ' + m.route.param('file'))];
},
},
});
No primeiro exemplo, ao acessar a rota padrão, m.route.param("id")
retornaria "1"
. No segundo exemplo, m.route.param("file")
retornaria pictures/image.jpg
.
Os parâmetros de rota podem ser delimitados por /
, -
ou .
. Isso permite criar segmentos de rota dinâmicos, oferecendo mais flexibilidade do que apenas um nome de caminho. Por exemplo, você pode corresponder rotas como "/edit/:name.:ext"
para editar com base na extensão do arquivo, ou /:lang-:region/view"
para uma rota localizada.
Parâmetros de rota são "gananciosos": dada uma rota definida como "/edit/:name.:ext"
, se você navegar para /edit/file.test.png
, os parâmetros extraídos serão {name: "file.test", ext: "png"}
, e não {name: "file", ext: "test.png"}
. Da mesma forma, dado "/route/:path.../view/:child..."
, se você acessar /route/foo/view/bar/view/baz
, os parâmetros extraídos serão {path: "foo/view/bar", child: "baz"}
.
Normalização de Parâmetros (Parameter normalization)
Parâmetros de rota interpolados em nomes de caminho são omitidos da query string por conveniência e para manter o nome do caminho legível. Por exemplo, o código abaixo envia uma requisição GET /api/user/1/connections?sort=name-asc
, omitindo o duplicado id=1
na URL.
m.request({
url: 'https://example.com/api/user/:userID/connections',
params: {
userID: 1,
sort: 'name-asc',
},
});
Você também pode especificar parâmetros explicitamente na query string, como neste exemplo, que é equivalente ao anterior:
m.request({
url: 'https://example.com/api/user/:userID/connections?sort=name-asc',
params: {
userID: 1,
},
});
E, claro, você pode combinar diferentes abordagens. O código abaixo envia uma requisição para GET /api/user/1/connections?sort=name-asc&first=10
.
m.request({
url: 'https://example.com/api/user/:userID/connections?sort=name-asc',
params: {
userID: 1,
first: 10,
},
});
Isso também se aplica à correspondência de rotas: é possível definir rotas com query strings explícitas. O parâmetro correspondente é retido para conveniência, permitindo o acesso através de parâmetros vnode ou via m.route.param
. Note que, embora isso seja possível, geralmente não é recomendado, já que você deve preferir caminhos para páginas. Pode ser útil em situações específicas onde você precisa gerar uma exibição ligeiramente diferente para um tipo de arquivo específico, mas que ainda é logicamente um parâmetro de consulta, e não uma página separada.
// Nota: isso geralmente *não* é recomendado - você deve preferir caminhos para declarações
// de rota, não strings de consulta.
m.route(document.body, '/edit/1', {
'/edit?type=image': {
view: function () {
return [m(Menu), m('h1', 'Editing photo')];
},
},
'/edit': {
view: function () {
return [m(Menu), m('h1', 'Editing ' + m.route.param('type'))];
},
},
});
Parâmetros de consulta são implicitamente aceitos - você não precisa nomeá-los para aceitá-los. Você pode corresponder com base em um valor existente, como em "/edit?type=image"
, mas você não precisa usar "/edit?type=:type"
para aceitar o valor. De fato, Mithril.js trataria isso como uma tentativa de corresponder literalmente contra m.route.param("type") === ":type"
, o que provavelmente não é o desejado. Em resumo, use m.route.param("key")
ou atributos de componente de rota para ler parâmetros de consulta.
Normalização de Caminho (Path normalization)
Rotas analisadas são sempre retornadas sem parâmetros duplicados ou barras extras, e sempre começam com uma barra. Essas pequenas diferenças podem causar problemas, tornando o roteamento e o tratamento de caminhos mais complicados do que o necessário. Mithril.js normaliza os caminhos internamente para roteamento, mas não expõe a rota atual e normalizada diretamente. (Você pode computá-la via m.parsePathname(m.route.get()).path
.)
Quando os parâmetros são desduplicados durante a correspondência, os parâmetros na query string têm precedência sobre os parâmetros no nome do caminho, e os parâmetros no final da URL têm precedência sobre os parâmetros mais próximos do início da URL.
Escapamento de Caminho (Path escaping)
Existem alguns caracteres que precisam ser escapados se você quiser usá-los literalmente. Por conveniência, encodeURIComponent
codifica esses (e outros) caracteres. Quando você substitui parâmetros e adiciona parâmetros de consulta, eles são codificados conforme necessário usando esta função. Os caracteres que Mithril.js interpreta são:
:
=%3A
/
=%2F
(requerido apenas em caminhos)%
=%25
?
=%3F
(requerido apenas em caminhos)#
=%23
Claro, existem outros caracteres que precisam ser codificados de acordo com a especificação da URL, como espaços. Mas, como mencionado anteriormente, encodeURIComponent
faz isso para você, e Mithril.js usa isso implicitamente quando você substitui parâmetros. Portanto, você só precisa se preocupar com o escape se estiver especificando parâmetros explicitamente, como em m.request("https://example.com/api/user/User%20Name/:field", {params: {field: ...}})
.