Einfache URL-Bearbeitung mit URLSearchParams

Die URLSearchParams API bietet eine einheitliche Oberfläche für die einzelnen Teile der URL und ermöglicht eine einfache Manipulation des Abfragestrings (der Teil nach ?).

Traditionell verwenden Entwickler reguläre Ausdrücke und String-Spaltung, um Abfrageparameter aus der URL zu extrahieren. Wenn wir alle ehrlich zu uns selbst sind, macht das keinen Spaß. Das kann mühsam und fehleranfällig sein. Eines meiner dunkelsten Geheimnisse ist, dass ich dieselben get|set|removeURLParameter Hilfsmethoden in mehreren großen Google.com-Apps wiederverwendet habe, darunter der Google Santa Tracker und die Google I/O 2015-Webversion.

Zeit für eine geeignete API, die diese Aufgaben für uns erledigt!

URLSearchParams API

Demo ansehen

Chrome 49 implementiert URLSearchParams aus der URL-Spezifikation, einer API, die sich zum Ausprobieren von URL-Suchparametern eignet. Ich sehe URLSearchParams als eine für URLs ebenso praktische Lösung wie FormData für Formulare.

Was können Sie damit tun? Anhand eines URL-Strings können Sie ganz einfach Parameterwerte extrahieren:

// Can also constructor from another URLSearchParams
const params = new URLSearchParams('q=search+string&version=1&person=Eric');

params.get('q') === "search string"
params.get('version') === "1"
Array.from(params).length === 3
for (let p of params) {
    console.log(p);
}

Legen Sie einen Parameterwert fest:

params.set('version', 2);

append Sie einen weiteren Wert für einen vorhandenen Parameter:

params.append('person', 'Tim');
params.getAll('person') === ['Eric', 'Tim']

Parameter löschen:

params.delete('person');

Mit URLs arbeiten

In den meisten Fällen arbeiten Sie wahrscheinlich mit vollständigen URLs oder ändern die URL Ihrer App. Der URL-Konstruktor kann in folgenden Fällen besonders nützlich sein:

const url = new URL('https://example.com?foo=1&bar=2');
const params = new URLSearchParams(url.search);
params.set('baz', 3);

params.has('baz') === true
params.toString() === 'foo=1&bar=2&baz=3'

Wenn Sie tatsächlich Änderungen an der URL vornehmen möchten, können Sie Parameter abrufen, ihre Werte aktualisieren und dann die URL mit history.replaceState aktualisieren.

// URL: https://example.com?version=1.0
const params = new URLSearchParams(location.search);
params.set('version', 2.0);

window.history.replaceState({}, '', `${location.pathname}?${params}`);
// URL: https://example.com?version=2.0

Hier habe ich ES6-Template-Strings verwendet, um eine aktualisierte URL aus dem vorhandenen URL-Pfad der App und den geänderten Parametern zu rekonstruieren.

Integration mit anderen Orts-URLs

Wenn du FormData in einer fetch() API-Anfrage sendest, wird standardmäßig ein mehrteiliger Textkörper erstellt. Bei Bedarf bietet URLSearchParams einen alternativen Mechanismus für POST-Daten, der nicht MIME-multipart, sondern URL-codiert ist.

const params = new URLSearchParams();
params.append('api_key', '1234567890');

fetch('https://example.com/api', {
    method: 'POST',
    body: params
}).then(...)

URLSearchParams ist zwar noch nicht in Chrome implementiert, kann aber auch in den URL-Konstruktor und in die a-Tags eingebunden werden. Beide unterstützen unseren neuen Freund, indem sie eine schreibgeschützte Property namens .searchParams für den Zugriff auf Abfrageparameter bereitstellen:

const url = new URL(location);
const foo = url.searchParams.get('foo') || 'somedefault';

Links erhalten auch eine .searchParams-Property:

const a = document.createElement('a');
a.href = 'https://example.com?filter=api';

// a.searchParams.get('filter') === 'api';

Funktionserkennung und Browserunterstützung

Derzeit wird URLSearchParams von Chrome 49, Firefox 44 und Opera 36 unterstützt.

if ('URLSearchParams' in window) {
    // Browser supports URLSearchParams
}

Ich empfehle die Polyfills unter github.com/WebReflection/url-search-params.

Demo

Probieren Sie es aus.

URLSearchParams in einer echten App sehen, können Sie den Material Design Iconset Generator von Polymer verwenden. Ich habe damit den Anfangsstatus der App über einen Deeplink eingerichtet. Sehr praktisch :)