URLクラスを使って、クエリストリングを簡単に扱う

URLクラスを使って、クエリストリングを簡単に扱う

みなさん。こんにちは。 久しぶりの投稿となります。

今回はとある案件でURLにクエリストリングを付与したり削除したりという機能を開発していた時、URLのクエリ部分をオブジェクトにしたり、そのオブジェクトをクエリストリングに戻したりという処理がすごく面倒だったので、 クエリストリングの操作が楽になるライブラリを探していた所、JavaScript(ES6以降)標準で入っているURLクラスで簡単にいったので記事にしてみました。

今回は、チェックボックスにチェックがついたらnewKeyというパラメーターがURLに追加されるようにしようと思います。

デモ

画面収録 2021-04-14 16.56.24.mov

HTML

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>URLSearchParamsを使ってみた</title>
</head>
<body>
<label>
    <input type="checkbox" id="js-checkbox">
    <span>クエリを付与</span>
</label>
<script src="./url-polyfill.js"></script><!-- IE11対応 -->
<script> //JSの処理 </script>
</body>
</html>
</code>
</pre>

JavaScript

const checkbox = document.getElementById('js-checkbox');
let paramsStr = window.location.search.substring(1); // window.location.searchから先頭の「?」を抜いた文字列を代入
let paramsArray = paramsStr.split('&'); // クエリストリングを「&」で分割したものを配列にする。
let paramsObject = {}; // 各キーと値のオブジェクト
let newParamsStr = '?'; // クエリストリング
if (paramsStr) {
    paramsArray.forEach(function (val, i) {
        let param = paramsArray[i].split('='); // キーと値を分離
        paramsObject[param[0]] = param[1]; // オブジェクトのキーを作成
    });
} // ここまでで、やっとオブジェクトが作成される。

function resetParamsStr() { // paramsObjectが変更された時にクエリストリングを再生成する関数
    newParamsStr = '?';
    let keys = Object.keys(paramsObject); // オブジェクトのキーを配列に
    let lastKeyIndex = keys.length - 1; // 最後のキーのindex番号
    if (keys.length) {
        keys.forEach(function (key, index) {
            newParamsStr += key+'='+paramsObject[key];
            if (index === lastKeyIndex) { // ループの最後だったら後ろに「&」はいらないので終了
                return;
            }
            newParamsStr += '&'; // 「&」を後ろにつける。
        });
    } else {
        newParamsStr = ''; // キーがない(objectが空だった場合)文字列を空にする
    }
    history.pushState(null, null, window.location.pathname + newParamsStr + window.location.hash); // URLを変更
}

checkbox.addEventListener('change', function () { // checkboxにイベントを追加
    let checked = checkbox.checked; // checkboxがチェックされているかどうか
    if (checked) {
        if ('newKey' in paramsObject) {
            return; // 既にキーが存在していたら何もしない
        }
        paramsObject['newKey'] = 'newValue'; // paramsObjectにキーを追加
        resetParamsStr(); // クエリストリングを再生成
    } else {
        if (!('newKey' in paramsObject)) {
            return; // キーが存在しなかったら何もしない
        }
        delete paramsObject.newKey; // paramsObjectからキーを削除
        resetParamsStr(); // クエリストリングを再生成
    }
});

クエリストリングをオブジェクトに変換するだけでsplitで分割して、キーと値をさらに分割して...などの色んな処理を挟み、とても長くすっきりしないコードになってしまいました。

※アンカーリンクを併用する場合は、下記の順番で入れます。 「URL + クエリストリング + #アンカー」 もし、 「URL + #アンカー + クエリストリング」 という順番で入れてしまうとwindow.location.searchが取得できないようです。

これをURLクラスを使って書き換えると以下になります。

const checkbox = document.getElementById('js-checkbox');
const url = new URL(window.location.href); // 現在のURLを素としたURLクラスのインスタンスを作り、url定数に格納
checkbox.addEventListener('change', function () {
    let checked = checkbox.checked;
    if (checked) {
        if (url.searchParams.has('newKey')) {
            return;
        }
        url.searchParams.append('newKey', 'newValue'); // クエリパラメーターにnewKeyを追加
    } else {
        if (!url.searchParams.has('newKey')) {
            return;
        }
        url.searchParams.delete('newKey'); // クエリパラメーターからnewKeyを削除
    }
    history.pushState(null, null, url.href); // URLを変更
});

とてもすっきりとしたコードになりました。 まず、二行目で現在のURLを素としたURLクラスのインスタンスを作り、url定数に格納します。

const url = new URL(window.location.href);

checkboxにチェックが入っていたら、下記のようにクエリパラメーターのキーを追加します。

url.searchParams.append('newKey', 'newValue');

checkboxのチェックがはずれていたら、下記のようにクエリパラメーターのキーを削除します。

url.searchParams.append('newKey', 'newValue');

最後にURLを書き換えます。url.hrefの中身はurl.searchParamsのキーを追加したり削除したりすることでクエリストリング部分が変化します。

history.pushState(null, null, url.href);

上のコードと比べていちいち、文字列→オブジェクト、オブジェクト→文字列と変換する手間もなくよっぽどシンプルになったかと思います。

また、URLクラスはIE11では非対応なので、IE11でも動作させたい場合は、下記のpolyfillを使ってください。 https://www.npmjs.com/package/url-polyfill

最後まで読んでいただき、ありがとうございました。

  • このエントリーをはてなブックマークに追加

この記事を読んだ人にオススメ