Manejo de Rutas
m.route
y m.request
comparten el concepto de ruta (path). Se utiliza para generar la URL a la que se redirige o desde la que se obtienen datos.
Tipos de Rutas
Existen dos tipos generales de rutas: rutas estáticas y rutas parametrizadas.
- Las rutas estáticas son simplemente cadenas que se utilizan directamente como URLs. No se realiza ninguna sustitución ni división. Simplemente se normalizan, añadiendo cualquier parámetro adicional al final.
- Las rutas parametrizadas permiten insertar valores en las URLs, que por defecto se escapan para mayor seguridad y protección contra inyección de URL.
Para m.request
, estas pueden ser prácticamente cualquier URL, pero para m.route
, solo pueden ser nombres de rutas absolutas sin esquemas ni dominios.
Parámetros de Ruta
Los parámetros de ruta son bastante simples. Se presentan de dos formas:
:foo
- Inyectaparams.foo
en la URL, escapando su valor previamente.:foo...
- Inyecta el valor crudo deparams.foo
en la URL, sin aplicar ningún escape.
El objeto params
es el que se pasa a m.route.set(path, params)
o m.request({url, params})
.
Al definir rutas con m.route(root, defaultRoute, routes)
, puede utilizar estos parámetros para extraer valores de las rutas. Funcionan de forma similar a la generación de rutas, pero en sentido inverso.
// Editar un solo elemento
m.route(document.body, '/edit/1', {
'/edit/:id': {
view: function () {
return [m(Menu), m('h1', 'Edición de usuario ' + m.route.param('id'))];
},
},
});
// Editar un elemento identificado por la ruta
m.route(document.body, '/edit/pictures/image.jpg', {
'/edit/:file...': {
view: function () {
return [m(Menu), m('h1', 'Edición de archivo ' + m.route.param('file'))];
},
},
});
En el primer ejemplo, asumiendo que se navega a la ruta por defecto en cada caso, m.route.param("id")
devolvería "1"
y m.route.param("file")
devolvería pictures/image.jpg
.
Los parámetros de ruta pueden estar delimitados por los caracteres /
, -
o .
. Esto permite tener segmentos de ruta dinámicos, lo que ofrece más flexibilidad que un simple nombre de ruta. Por ejemplo, podría coincidir con rutas como "/edit/:name.:ext"
para editar basándose en la extensión del archivo o /:lang-:region/view
para una ruta localizada.
Los parámetros de ruta son greedy (voraces): dada una ruta definida como "/edit/:name.:ext"
, si se navega a /edit/file.test.png
, los parámetros extraídos serán {name: "file.test", ext: "png"}
, no {name: "file", ext: "test.png"}
. De manera similar, dado "/route/:path.../view/:child..."
, si se navega a /route/foo/view/bar/view/baz
, los parámetros extraídos serán {path: "foo/view/bar", child: "baz"}
.
Normalización de Parámetros
Los parámetros de ruta que se interpolan en los nombres de ruta se omiten de la cadena de consulta (query string), por conveniencia y para que el nombre de la ruta sea más legible. Por ejemplo, esto envía una solicitud GET
a /api/user/1/connections?sort=name-asc
, omitiendo el duplicado id=1
en la cadena de consulta.
m.request({
url: 'https://example.com/api/user/:userID/connections',
params: {
userID: 1,
sort: 'name-asc',
},
});
También se pueden especificar los parámetros explícitamente en la propia cadena de consulta, como en este caso, que es equivalente al anterior:
m.request({
url: 'https://example.com/api/user/:userID/connections?sort=name-asc',
params: {
userID: 1,
},
});
Y, por supuesto, puede mezclar y combinar. Esto genera una solicitud 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,
},
});
Esto también se aplica a la coincidencia de rutas: puede coincidir con una ruta con cadenas de consulta explícitas. Conserva el parámetro coincidente para mayor comodidad, por lo que aún puede acceder a ellos a través de los parámetros del vnode o a través de m.route.param
. Tenga en cuenta que, aunque esto es posible, generalmente no se recomienda; es preferible usar rutas para las páginas. A veces podría ser útil si se necesita generar una vista ligeramente diferente solo para un tipo de archivo en particular, pero lógicamente sigue siendo un parámetro de consulta, no una página separada completa.
// Nota: esto generalmente *no* se recomienda - debe preferir las rutas para las
// declaraciones de ruta, no las cadenas de consulta.
m.route(document.body, '/edit/1', {
'/edit?type=image': {
view: function () {
return [m(Menu), m('h1', 'Editando foto')];
},
},
'/edit': {
view: function () {
return [m(Menu), m('h1', 'Editando ' + m.route.param('type'))];
},
},
});
Los parámetros de consulta se consumen implícitamente; no es necesario nombrarlos para aceptarlos. Puede hacer coincidir basándose en un valor existente, como en "/edit?type=image"
, pero no necesita usar "/edit?type=:type"
para aceptar el valor. De hecho, Mithril.js trataría eso como si estuviera intentando coincidir literalmente con m.route.param("type") === ":type"
, por lo que probablemente no querrá hacer eso. En resumen, use m.route.param("key")
o los atributos del componente de ruta para leer los parámetros de consulta.
Normalización de Rutas
Las rutas procesadas siempre se devuelven con todos los parámetros duplicados y las barras diagonales adicionales eliminadas, y siempre comienzan con una barra diagonal. Estas pequeñas diferencias a menudo dificultan el proceso, y hacen que el enrutamiento y el manejo de rutas sean más complicados de lo necesario. Mithril.js normaliza internamente las rutas para el enrutamiento, pero no expone la ruta actual y normalizada directamente. (Podría calcularlo a través de m.parsePathname(m.route.get()).path
.)
Cuando se eliminan los parámetros duplicados durante la coincidencia, se da prioridad a los parámetros de la cadena de consulta sobre los del nombre de la ruta, y a los parámetros al final de la URL sobre los del principio.
Escape de Rutas
Hay ciertos caracteres que, si se quieren utilizar literalmente, deben escaparse. Convenientemente, encodeURIComponent
codifica estos (y más), y cuando sustituye parámetros y agrega parámetros de consulta, se codifican según sea necesario utilizando esto. Aquí están los que interpreta Mithril.js:
:
=%3A
/
=%2F
(requerido solo en rutas)%
=%25
?
=%3F
(requerido solo en rutas)#
=%23
Por supuesto, hay otros que debe escapar según la especificación de la URL, como los espacios. Pero como ya se señaló, encodeURIComponent
lo hace por usted, y Mithril.js lo usa implícitamente cuando sustituye parámetros. Por lo tanto, solo es necesario preocuparse si se están especificando parámetros explícitamente, como en m.request("https://example.com/api/user/User%20Name/:field", {params: {field: ...}})
.