Przestań parsować URL sztuczkami na stringach
Zanim pojawiło się API URL, adresy cięło się przez split('?'), wyrażenia regularne i nadzieję. Zwykle działało, dopóki wartość nie zawierała &, =, spacji albo znaku spoza ASCII, a wtedy przestawało. Zarówno przeglądarka, jak i Node mają porządny parser. Korzystaj z niego.
Jedno wywołanie i każda część adresu jest już rozdzielona i poprawnie zdekodowana. Przy niepoprawnych danych konstruktor rzuca TypeError, a zwykle właśnie tego chcesz: bezsensowny URL powinien głośno zawieść, zamiast po cichu produkować bzdury dalej w kodzie.
Odczyt parametrów zapytania
Każdy URL ma właściwość .searchParams, czyli obiekt URLSearchParams, który umie czytać i zapisywać query string:
Kilka rzeczy, na które warto zwrócić uwagę:
- Wartości wracają już zdekodowane.
?name=Ada%20Lovelacedaje"Ada Lovelace". - Wszystko jest stringiem.
"2"to nie2. Jeśli potrzebujesz liczby, zamień przezNumber(). - Powtórzone klucze są dozwolone.
getzwraca pierwsze dopasowanie,getAllzwraca wszystkie. - Brakujące klucze zwracają
null, a nieundefined, więc?? "default"dobrze z nimi działa.
Budowanie query stringa
Query string możesz zbudować od zera przez URLSearchParams, bez ręcznego escapowania i bez łączenia przez &:
Albo utworzyć go z obiektu: działa dowolny iterowalny zbiór par [key, value], a także zwykły obiekt:
set a append: set zastępuje istniejącą wartość dla danego klucza, append dodaje kolejną. Używaj append, gdy klucz może się zasadnie powtarzać (tagi, filtry), a set dla parametrów o pojedynczej wartości.
Modyfikowanie URL
Ponieważ URL to żywy obiekt, zmiana searchParams automatycznie aktualizuje .search i .href:
To idiomatyczny sposób dodawania parametru zapytania do istniejącego adresu. Bez sprawdzania, czy URL ma już ?, i bez zastanawiania się, czy dokleić & czy ?.
W ten sam sposób możesz zmieniać inne części adresu:
Iterowanie po parametrach
URLSearchParams jest iterowalny. for...of daje pary [key, value], są też standardowe pomocniki keys(), values() i entries():
Zauważ, że powtórzone klucze pojawiają się wielokrotnie: zobaczysz tag = web, a potem tag = beginner jako osobne wpisy. To wiernie odpowiada faktycznemu query stringowi.
Jeśli chcesz zwykły obiekt do szybkiego wypisania przy debugowaniu, zadziała Object.fromEntries, ale scala on powtórzenia i zostawia tylko ostatnią wartość:
Do debugowania wystarczy. Źle, jeśli jakikolwiek klucz może się powtarzać.
Względne adresy potrzebują bazy
Samo new URL("/search?q=js") rzuca błąd: ścieżka względna nie jest sama w sobie poprawnym adresem URL. Przekaż bazę jako drugi argument:
Reguły rozwiązywania są takie same, jakich przeglądarki używają dla <a href>: początkowy / oznacza ścieżkę bezwzględną od hosta, brak ukośnika oznacza ścieżkę względną wobec bieżącej, a .. przechodzi poziom wyżej. Bardzo wygodne, gdy składasz adresy API ze skonfigurowanej bazy.
W przeglądarce window.location.href to gotowa baza do parsowania adresu bieżącej strony:
const u = new URL(window.location.href);
const page = u.searchParams.get("page") ?? "1";
Obsługa niepoprawnych adresów
Konstruktor URL rzuca błąd przy źle sformatowanych danych. To przydatne, ale oznacza, że potrzebujesz try/catch przy parsowaniu wszystkiego, co wpisał użytkownik albo przysłał zewnętrzny system:
Nowoczesne środowiska udostępniają też URL.canParse(input), czyli sprawdzenie zwracające boolean, które pozwala uniknąć zabawy z try/catch, gdy chcesz tylko walidować:
Mały działający przykład
Wszystko razem: odczytaj bieżące filtry z adresu, zmień je i utwórz nowy URL, na który można przejść:
Przekazanie null usuwa parametr. Każda inna wartość go ustawia albo nadpisuje. W takiej czy innej formie napiszesz ten wzorzec za każdym razem, gdy budujesz interfejs filtrów, paginację albo deep linki.
Co warto zapamiętać
new URL(string)rozkłada adres na nazwane części. Przy bzdurach rzuca błąd.url.searchParamstoURLSearchParams: używajget,getAll,set,append,delete,has.- Kodowanie dzieje się samo. Nie sięgaj po
encodeURIComponent, chyba że budujesz stringi ręcznie. - Przekaż bazowy URL jako drugi argument, żeby rozwiązać ścieżki względne.
URL.canParse(albotry/catch) to twoje narzędzie do walidacji niezaufanych danych.
Za każdym razem, gdy kusi cię podzielenie adresu przez .split('?') albo wyłowienie parametru zapytania regexem, sięgnij zamiast tego po te API. Są krótsze, poprawne i już wbudowane w środowisko.
Najczęściej zadawane pytania
Jak sparsować URL w JavaScript?
Przekaż string do konstruktora URL: const u = new URL('https://example.com/path?x=1'). Powstały obiekt udostępnia protocol, host, pathname, search, hash oraz pomocnika searchParams. Przy niepoprawnych adresach rzuca błąd, więc przy parsowaniu niezaufanych danych opakuj go w try/catch.
Jak odczytać parametr z query stringa w JavaScript?
Użyj url.searchParams.get('name'). Zwraca zdekodowaną wartość albo null, jeśli parametru nie ma. Dla parametrów, które mogą się powtarzać (?tag=a&tag=b), użyj searchParams.getAll('tag'), żeby dostać wszystkie wartości jako tablicę.
Czym różni się URL od URLSearchParams?
URL parsuje i reprezentuje cały adres: protokół, host, ścieżkę, zapytanie, hash. URLSearchParams to tylko część z query stringiem i możesz go używać samodzielnie do budowania albo parsowania stringów w stylu a=1&b=2. Każda instancja URL ma właściwość .searchParams, która jest obiektem URLSearchParams powiązanym z tym adresem.
Czy parametry zapytania trzeba kodować ręcznie?
Nie. URLSearchParams automatycznie koduje klucze i wartości, gdy wywołujesz set, append albo odczytujesz string. Poprawnie obsługuje spacje, &, = i Unicode. Po encodeURIComponent sięgaj tylko wtedy, gdy budujesz string ręcznie, a zwykle nie powinieneś tego robić.