Edited at

URLSearchParamsによる簡単URL操作

More than 3 years have passed since last update.

JavaScriptでURL文字列を操作するのは、実は結構骨が折れる作業です。特に、クエリパラメータを個々に取り出す処理などは、毎回車輪の再発明を皆さんしてきたのではないでしょうか?URLSearchParamsを使うことで、もう再発明をすることはありません。Firefox 44、Opera 36で使えて、Chrome 49からも使えるようになります。

Google Developersに「Easy URL manipulation with URLSearchParams」という記事がありましたので、日本語訳を作ってみました。

(このエントリは、自分のブログポストと同じ内容です)


URLSearchParams APIは、URLの細々したものへの一貫性のあるインタフェースを提供し、そしてクエリ文字列("?"の後のもの)のありふれた操作を可能にします。

慣習的に、URLからクエリパラメータを引き出すために、開発者は正規表現や文字列分割を使います。もし私たち自身が皆正直であれば、それは楽しいことではありません。それはうんざりさせ、そしてエラーを引き起こす傾向があります。私の秘密の一つは、GoogleサンタトラッカーやGoogle I/O 2015ウェブサイトを含むいくつかの大きなGoogle.comアプリにおいて、同じget、set、removeURLParameterというヘルパーメソッドを再利用しました。

この作業をするための適切なAPIを使う時が私たちに来ました!


URLSearchParams

デモを試す

Chrome 49は、URL仕様から、URLクエリパラメータをあれこれいじくり回すAPIであるURLSearchParamsを実装しました。URLSearchParamsは、フォームのためにあったFormDataと同じような便利さをURLSearchParamsはURLにもたらすと考えています。

さて、それを使ってあなたは何ができるでしょう?URL文字列が与えられた時、あなたは簡単にパラメータ値を展開することができます:

// もう一つのURLSearchParamsから作成することもできます

let params = new URLSearchParams('q=search+string&version=1&person=Eric');

params.get('q') === "search string"
params.get('version') === "1"

注意: もし一つのパラメータにいくつかの値がある場合は、getは最初の値を返します。複数のパラメータを横断して操作する場合は以下になります:

for (let p of params) {

console.log(p);
}

パラメータ値をセットする場合は以下になります:

params.set('version', 2);

注意: もしいくつかの値がある場合は、setは同じ名前の全ての他のパラメータを削除します。

既存パラメータにもう一つ値を追加する場合は以下になります:

params.append('person', 'Tim');

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

パラメータ(複数)を削除する場合は以下になります:

params.delete('person');

注意: この例は、最初に出現したものだけでなく、全てのpersonクエリパラメータをURLから削除します。


URLとの作用

ほとんどの時間、あなたはおそらくフルなURLを扱うか、もしくはあなたのアプリのURLを修正するでしょう。URL構築は、これらのケースに対して特に手軽に行えます。

let url = new URL('https://example.com?foo=1&bar=2');

let params = new URLSearchParams(url.search.slice(1));
params.set('baz', 3);

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

URLを実際に変更するために、あなたはパラメータを取得し、それらの値を更新し、その後history.replaceStateを使ってUTLを更新することができます。

// URL: https://example.com?version=1.0

let params = new URLSearchParams(location.search.slice(1));
params.set('version', 2.0);

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

ここでは、アプリの既存URLと修正されたパラメータから更新されたURLを再構築するために、私はES6のtemplate stringを使いました。


URLが使われている他の場所への統合

初期動作として、fetch() APIリクエスト内のFormData送信は、マルチパートボディを作ります。もしあなたがそれを必要とするならば、URLSearchParamsは、MIMEマルチパートではなくURLエンコードされたPOSTデータのための代替機構を提供します。

let params = new URLSearchParams();

params.append('api_key', '1234567890');

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

Chromeではまだ実装されていませんが、URLSearchParamsはURLコンストラクタやタグとも統合します。この両方が、クエリパラメータにアクセスするための.searchParamsという読み込み専用のプロパティの提供によって、私たちの新しい仲間をサポートします:

// 注意: URLの.searchParamsはChrome 49では実装されていません。

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

リンクもまた.searchParamsプロパティを得ます:

// 注意: リンクの.searchParamsはChrome 49では実装されていません。

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

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


機能の発見とブラウザサポート

現在、Chrome 49、Firefox 44、そしてOpera 36が、URLSearchParamsをサポートしています。

if ('URLSearchParams' in window) {

// ブラウザはURLSearchParamsをサポートします
}

ポリフィルとして、私はgithub.com/WebReflection/url-search-paramsのものを勧めます。


デモ

sampleを試してみて下さい!

現実世界のアプリでURLSearchParamsを見るために、Polymer's material design Iconset Generatorをチェックしてみてください。私はディープリンクからアプリの初期状態をセットアップするためにそれを使いました。とても手軽です。 :)