Gestione dei Percorsi
m.route
e m.request
condividono un concetto di percorso (path). Questo viene utilizzato per generare l'URL a cui si naviga o da cui si recuperano i dati.
Tipi di Percorso
Esistono due tipi principali di percorsi: percorsi statici e percorsi parametrizzati.
- I percorsi statici sono semplicemente stringhe utilizzate direttamente come URL, senza sostituzioni o elaborazioni. Vengono normalizzati aggiungendo eventuali parametri alla fine come query string.
- I percorsi parametrizzati consentono di inserire valori dinamici all'interno dei percorsi, con codifica automatica per garantire comodità e sicurezza contro attacchi di iniezione di URL.
Per m.request
, questi possono essere qualsiasi URL valido. Per m.route
, possono essere solo nomi di percorso URL assoluti, senza schemi o domini.
Parametri del Percorso
I parametri del percorso sono piuttosto semplici. Si presentano in due forme:
:foo
- Inserisce il valore diparams.foo
nell'URL, dopo averlo codificato.:foo...
- Inserisce il valore diparams.foo
nell'URL come segmento di percorso, senza codifica.
L'oggetto params
è il parametro params
in m.route.set(path, params)
e m.request({url, params})
.
Quando si definiscono le rotte tramite m.route(root, defaultRoute, routes)
, è possibile utilizzare questi parametri per estrarre valori dagli URL. Funzionano in modo simile alla generazione dei percorsi, ma in direzione opposta.
// Modifica un singolo elemento
m.route(document.body, '/edit/1', {
'/edit/:id': {
view: function () {
return [m(Menu), m('h1', 'Modifica utente ' + m.route.param('id'))];
},
},
});
// Modifica un elemento identificato dal percorso
m.route(document.body, '/edit/pictures/image.jpg', {
'/edit/:file...': {
view: function () {
return [m(Menu), m('h1', 'Modifica file ' + m.route.param('file'))];
},
},
});
Nel primo esempio, navigando verso la route predefinita, m.route.param("id")
restituirà "1"
. Nel secondo esempio, m.route.param("file")
restituirà pictures/image.jpg
.
I parametri del percorso possono essere delimitati da /
, -
o .
. Consentono segmenti di percorso dinamici e sono più flessibili di un semplice nome di percorso. Ad esempio, si potrebbe definire una route come "/edit/:name.:ext"
per la modifica in base all'estensione del file, oppure /:lang-:region/view"
per una route localizzata.
I parametri del percorso seguono una logica "greedy": data una route "/edit/:name.:ext"
, se si naviga verso /edit/file.test.png
, i parametri estratti saranno {name: "file.test", ext: "png"}
, e non {name: "file", ext: "test.png"}
. Allo stesso modo, data la route "/route/:path.../view/:child..."
, navigando verso /route/foo/view/bar/view/baz
, i parametri estratti saranno {path: "foo/view/bar", child: "baz"}
.
Normalizzazione dei Parametri
I parametri del percorso che vengono interpolati nei nomi dei percorsi vengono omessi dalla query string, per migliorare la leggibilità e la chiarezza dell'URL. Ad esempio, il codice seguente invia una richiesta GET /api/user/1/connections?sort=name-asc
al server, omettendo il duplicato id=1
nella query string.
m.request({
url: 'https://example.com/api/user/:userID/connections',
params: {
userID: 1,
sort: 'name-asc',
},
});
È anche possibile specificare i parametri esplicitamente nella query string, ottenendo lo stesso risultato:
m.request({
url: 'https://example.com/api/user/:userID/connections?sort=name-asc',
params: {
userID: 1,
},
});
Naturalmente, è possibile combinare i due approcci. Il codice seguente invia una richiesta 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,
},
});
Questo comportamento si estende anche alla corrispondenza delle rotte: è possibile definire una route con query string esplicite. Il parametro corrispondente viene mantenuto per comodità, quindi è possibile accedervi tramite i parametri del vnode o tramite m.route.param
. Tuttavia, questo approccio generalmente non è raccomandato, poiché è preferibile utilizzare i percorsi per definire le rotte. Potrebbe essere utile in alcuni casi per generare una vista leggermente diversa per un tipo di file specifico, ma concettualmente rimane un parametro di query, non una pagina distinta.
// Nota: questo generalmente *non* è raccomandato - è preferibile utilizzare i percorsi per la dichiarazione
// delle rotte, non le query string.
m.route(document.body, '/edit/1', {
'/edit?type=image': {
view: function () {
return [m(Menu), m('h1', 'Modifica foto')];
},
},
'/edit': {
view: function () {
return [m(Menu), m('h1', 'Modifica ' + m.route.param('type'))];
},
},
});
I parametri della query vengono implicitamente acquisiti: non è necessario nominarli per accettarli. È possibile confrontare in base a un valore esistente, come in "/edit?type=image"
, ma non è necessario utilizzare "/edit?type=:type"
per ricevere il valore. Infatti, Mithril.js lo interpreterebbe come un tentativo di confrontare m.route.param("type")
con la stringa ":type"
, il che probabilmente non è l'intento. In sintesi, utilizzare m.route.param("key")
o gli attributi del componente route per leggere i parametri della query.
Normalizzazione del Percorso
I percorsi analizzati vengono sempre restituiti senza parametri duplicati o barre extra, e iniziano sempre con una barra. Queste piccole differenze possono complicare la gestione del routing e dei percorsi. Mithril.js normalizza internamente i percorsi per il routing, ma non espone direttamente il percorso normalizzato corrente. (È possibile calcolarlo tramite m.parsePathname(m.route.get()).path
.)
Quando i parametri vengono deduplicati durante la corrispondenza, i parametri nella query string hanno la precedenza sui parametri nel nome del percorso, e i parametri verso la fine dell'URL hanno la precedenza sui parametri più vicini all'inizio dell'URL.
Escape del Percorso
Alcuni caratteri devono essere sottoposti a escape se si desidera utilizzarli letteralmente. La funzione encodeURIComponent
codifica questi caratteri (e altri), e viene utilizzata automaticamente per codificare i parametri quando vengono sostituiti o aggiunti alla query string. Ecco i caratteri che Mithril.js interpreta in modo speciale:
:
=%3A
/
=%2F
(richiesto solo nei percorsi)%
=%25
?
=%3F
(richiesto solo nei percorsi)#
=%23
Naturalmente, ci sono altri caratteri che devono essere sottoposti a escape secondo le specifiche dell'URL, come gli spazi. Come già detto, encodeURIComponent
lo fa automaticamente e Mithril.js lo utilizza implicitamente quando si sostituiscono i parametri. Pertanto, è necessario prestare attenzione solo quando si specificano i parametri esplicitamente, come in m.request("https://example.com/api/user/User%20Name/:field", {params: {field: ...}})
.