Manipulación sencilla de URL con URLSearchParams

La API de URLSearchParams proporciona una interfaz coherente para los fragmentos y las partes de la URL y permite una manipulación trivial de la cadena de consulta (ese elemento después de ?).

Tradicionalmente, los desarrolladores usan regex y división de cadenas para extraer parámetros de consulta de la URL. Si todos somos honestos con nosotros mismos, no es divertido. Hacerlo bien puede ser tedioso y propenso a errores. Uno de mis secretos es que reutilicé los mismos métodos auxiliares get|set|removeURLParameter en varias apps grandes de Google.com, como Sigue a Papá Noel de Google y la Web de Google I/O 2015.

Es momento de una API adecuada que se encargue de todo esto.

API de URLSearchParams

Probar la demostración

Chrome 49 implementa URLSearchParams desde la especificación de la URL, una API que es útil para ajustar los parámetros de consulta de URL. Considero que URLSearchParams es una conveniencia equivalente a las URLs, al igual que FormData para los formularios.

Entonces, ¿qué puedes hacer con él? Para una cadena de URL, puedes extraer fácilmente valores de parámetros:

// 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);
}

set un valor del parámetro:

params.set('version', 2);

append otro valor a un parámetro existente:

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

delete un parámetro o varios:

params.delete('person');

Cómo trabajar con URLs

La mayoría de las veces, es probable que trabajes con URLs completas o modifiques la URL de tu app. El constructor URL puede ser particularmente útil en estos casos:

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'

Para realizar cambios reales en la URL, puedes tomar los parámetros, actualizar sus valores y, luego, usar history.replaceState para actualizar la URL.

// 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

Aquí, usé strings de plantilla de ES6 para reconstruir una URL actualizada a partir de la ruta de URL existente de la app y los parámetros modificados.

Integración con otras URLs de lugares

De forma predeterminada, el envío de FormData en una solicitud a la API fetch() crea un cuerpo de varias partes. Si lo necesitas, URLSearchParams proporciona un mecanismo alternativo a los datos POST codificados en formato URL en lugar de MIME de varias partes.

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

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

Aunque aún no se implementó en Chrome, URLSearchParams también se integra con el constructor URL y las etiquetas a. Ambos son compatibles con nuestro nuevo amigo, ya que proporcionan una propiedad de solo lectura, .searchParams, para acceder a los parámetros de consulta:

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

Los vínculos también obtienen una propiedad .searchParams:

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

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

Detección de funciones y compatibilidad con navegadores

Actualmente, Chrome 49, Firefox 44 y Opera 36 admiten URLSearchParams.

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

Para polyfills, te recomiendo el que se encuentra en github.com/WebReflection/url-search-params.

Demostración

Prueba la muestra.

Para ver URLSearchParams en una app real, consulta el Generador de Iconsets de Material Design de Polymer. Lo usé para configurar el estado inicial de la app desde un vínculo directo. Es bastante útil :)