Obsługa ścieżek
m.route
i m.request
wykorzystują koncepcję ścieżki. Służy ona do generowania adresów URL, do których przekierowujesz lub z których pobierasz dane.
Typy ścieżek
Wyróżniamy dwa główne typy ścieżek: ścieżki statyczne i ścieżki parametryzowane.
- Ścieżki statyczne to zwykłe ciągi znaków używane bezpośrednio jako adresy URL. Nie są one modyfikowane ani dzielone, a jedynie normalizowane poprzez dołączenie parametrów na końcu.
- Ścieżki parametryzowane umożliwiają wstawianie wartości do adresów URL, domyślnie z odpowiednim kodowaniem (escaping), co zapewnia wygodę i chroni przed atakami typu URL injection.
W przypadku m.request
mogą to być praktycznie dowolne adresy URL, natomiast dla routingu mogą to być tylko bezwzględne nazwy ścieżek URL bez schematów i domen.
Parametry ścieżki
Parametry ścieżki są stosunkowo proste. Występują w dwóch formach:
:foo
- Wstawia wartośćparams.foo
do adresu URL, uprzednio ją kodując.:foo...
- Wstawia surową ścieżkęparams.foo
do adresu URL bez kodowania.
Obiekt params
to po prostu argument params
w m.route.set(path, params)
oraz m.request({url, params})
.
Podczas definiowania routingu za pomocą m.route(root, defaultRoute, routes)
, możesz użyć tych parametrów do wyodrębniania wartości ze ścieżek. Działa to analogicznie do generowania ścieżek, z tą różnicą, że proces odbywa się w odwrotnym kierunku.
// Edycja pojedynczego elementu
m.route(document.body, '/edit/1', {
'/edit/:id': {
view: function () {
return [m(Menu), m('h1', 'Edytowanie użytkownika ' + m.route.param('id'))];
},
},
});
// Edycja elementu identyfikowanego przez ścieżkę
m.route(document.body, '/edit/pictures/image.jpg', {
'/edit/:file...': {
view: function () {
return [m(Menu), m('h1', 'Edytowanie pliku ' + m.route.param('file'))];
},
},
});
W pierwszym przykładzie, przy założeniu domyślnej ścieżki, m.route.param("id")
zwróci "1"
, a m.route.param("file")
w drugim przykładzie zwróci pictures/image.jpg
.
Parametry ścieżki mogą być oddzielone znakami /
, -
lub .
. Umożliwia to tworzenie dynamicznych segmentów ścieżki i zapewnia większą elastyczność niż tylko nazwy ścieżek. Na przykład, możesz dopasować routing do ścieżek takich jak "/edit/:name.:ext"
w celu edycji na podstawie rozszerzenia pliku lub /:lang-:region/view
dla zlokalizowanej ścieżki.
Parametry ścieżki są "zachłanne": mając zadeklarowaną ścieżkę "/edit/:name.:ext"
, jeśli przejdziesz do /edit/file.test.png
, wyodrębnione parametry będą miały postać {name: "file.test", ext: "png"}
, a nie {name: "file", ext: "test.png"}
. Podobnie, mając "/route/:path.../view/:child..."
, jeśli przejdziesz do /route/foo/view/bar/view/baz
, wyodrębnione parametry będą miały postać {path: "foo/view/bar", child: "baz"}
.
Normalizacja parametrów
Parametry ścieżki, które są interpolowane do nazw ścieżek, są pomijane w parametrach zapytania, co poprawia czytelność samej nazwy ścieżki. Na przykład, poniższy kod wysyła żądanie do serwera GET /api/user/1/connections?sort=name-asc
, pomijając duplikat id=1
w ciągu adresu URL.
m.request({
url: 'https://example.com/api/user/:userID/connections',
params: {
userID: 1,
sort: 'name-asc',
},
});
Możesz również jawnie określić parametry w parametrach zapytania, jak w poniższym przykładzie, który jest równoważny powyższemu:
m.request({
url: 'https://example.com/api/user/:userID/connections?sort=name-asc',
params: {
userID: 1,
},
});
Oczywiście, możesz łączyć te metody. Poniższy kod wysyła żądanie do 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,
},
});
Dotyczy to również dopasowywania tras: możesz dopasować trasę z jawnymi ciągami zapytania. Dopasowany parametr jest zachowywany dla wygody, więc nadal możesz uzyskać do niego dostęp za pomocą parametrów vnode lub za pomocą m.route.param
. Należy jednak pamiętać, że choć jest to możliwe, generalnie zaleca się stosowanie ścieżek dla stron. Może to być przydatne w sytuacjach, gdy potrzebny jest nieco odmienny widok dla określonego typu pliku. Należy jednak pamiętać, że logicznie rzecz biorąc, jest to parametr podobny do zapytania, a nie oddzielna strona.
// Uwaga: to generalnie *nie* jest zalecane - powinieneś preferować ścieżki dla deklaracji
// routingu, a nie ciągi zapytania.
m.route(document.body, '/edit/1', {
'/edit?type=image': {
view: function () {
return [m(Menu), m('h1', 'Edycja zdjęcia')];
},
},
'/edit': {
view: function () {
return [m(Menu), m('h1', 'Edycja ' + m.route.param('type'))];
},
},
});
Parametry zapytania są konsumowane niejawnie - nie jest wymagane ich jawne definiowanie, aby zostały zaakceptowane. Możesz dopasować na podstawie istniejącej wartości, tak jak w "/edit?type=image"
, ale nie musisz używać "/edit?type=:type"
, aby zaakceptować wartość. W rzeczywistości Mithril.js traktowałby to tak, jakbyś próbował dosłownie dopasować do m.route.param("type") === ":type"
, więc prawdopodobnie nie chcesz tego robić. Krótko mówiąc, użyj m.route.param("key")
lub atrybutów komponentu routingu, aby odczytać parametry zapytania.
Normalizacja ścieżki
Przeanalizowane ścieżki są zawsze zwracane po usunięciu zduplikowanych parametrów i dodatkowych ukośników, i zawsze zaczynają się od ukośnika. Te drobne różnice często utrudniają routing i obsługę ścieżek. Mithril.js wewnętrznie normalizuje ścieżki dla routingu, ale nie udostępnia bezpośrednio bieżącej, znormalizowanej ścieżki. (Możesz ją obliczyć za pomocą m.parsePathname(m.route.get()).path
.)
Gdy parametry są deduplikowane podczas dopasowywania, parametry w ciągu zapytania mają pierwszeństwo przed parametrami w nazwie ścieżki, a parametry na końcu adresu URL mają pierwszeństwo przed parametrami bliżej początku adresu URL.
Kodowanie ścieżek
Istnieją znaki, które, jeśli chcesz ich używać dosłownie, musisz zakodować. Funkcja encodeURIComponent
wygodnie koduje te (i inne) znaki. Podczas podstawiania parametrów i dodawania parametrów zapytania, są one kodowane w razie potrzeby właśnie za jej pomocą. Oto znaki interpretowane przez Mithril.js:
:
=%3A
/
=%2F
(wymagane tylko w ścieżkach)%
=%25
?
=%3F
(wymagane tylko w ścieżkach)#
=%23
Oczywiście, istnieją inne znaki, które musisz zakodować zgodnie ze specyfikacją URL, takie jak spacje. Ale jak już wspomniano, encodeURIComponent
robi to za ciebie, a Mithril.js używa tego niejawnie, gdy podstawiasz parametry. Dlatego należy o tym pamiętać tylko w przypadku jawnego określania parametrów, na przykład w m.request("https://example.com/api/user/User%20Name/:field", {params: {field: ...}})
.