JavaScriptでURLパラメータ、ちゃんと扱えてる? Vue.jsでも使える、安全な取得と更新

こんにちは、さるまりんです 🐒🔧

Vue.js や JavaScript で画面を作っていると、
いつの間にか使っているのが URLパラメータ

?mode=edit&page=2

「とりあえず取れてるからOK」
「なんとなく動いてるからOK」

……そんな感じで、
僕も いい加減に扱ってしまっている ことがありました。

やっていて思うのは、
URLパラメータって あとから地味にハマりやすい んですよね。

ということで今回は、

  • URLパラメータって何?
  • JavaScriptでどう扱うのが安全?
  • Vue.js で使うときの考え方

を、実際に試しながら整理してみます。

URLパラメータって、そもそも何?

URLパラメータは、URLの中の ? 以降の部分です。

https://example.com/list?mode=edit&page=2

この

?mode=edit&page=2

クエリパラメータ

よくある使い道は:

  • 表示する内容(データ)の指定
  • 表示モードの切り替え
  • ページ番号
  • フィルタ条件
  • タブ状態の保持

つまり、

URLに画面の状態を保存している

というイメージになります。

シンプルな書き方(そして罠)

最初にやりがちなのが、これ。

const query = location.search;
console.log(query);

location.search で ? 以降がすべて取れます。

結果:

?mode=edit&page=2

ここから、

query.replace("?", "");
query.split("&");

……と、
自前でパースし始める パターン。

もちろんこれは動きますし、
仕組みを理解するには大事なことでもあります。

でも、やっているとこうなります。

  • エンコードはどうする?
  • 値が無い場合は?
  • 同じキーが複数あったら?

「どうする?」がどんどん増えていきます。

みんな同じ問題にぶつかってきたんですよね。
だからこそ、ちゃんと用意されています。

URLSearchParams を使う

JavaScript には、最初から便利なAPIがあります。

const params = new URLSearchParams(location.search);

これで、クエリを安全に扱えるようになります。

取得

params.get("mode"); // "edit"
params.get("page"); // "2"

追加・更新

params.set("page", "3");

削除

params.delete("mode");

文字列操作を一切しなくてOK
というのが、かなり大きいです。

「setしたのにURLが変わらない?」問題

ここで、一度ハマりやすいポイントがあります。

params.set("page", "3");

これを実行しても、
ブラウザのURLは変わりません。

気持ちとしては、
?page=3 になってほしいですよね?

でも、なりません。

なぜかというと、

👉 URLSearchParams は
URLそのものを書き換えるものではない からです。

反映させるには、こうします。

const newUrl =
    location.pathname + "?" + params.toString();

history.replaceState(null, "", newUrl);

これで、実際のURLが変わります。

ここで出てきた history
履歴を操作しているんですね。

replaceState と pushState の違い

  •  replaceState
    → 履歴を汚さない(今の状態を置き換える)
  • pushState
    → 履歴を残したいとき(戻るボタン対応など)

この違い、意外と大事です。

hash (#…) を一緒に扱うときの注意

URLに hash がある場合:

/list?page=2#detail

そのまま location.pathname だけでURLを組み立てると、
hash が消えてしまう ことがあります。

安全に書くなら:

const newUrl =
    location.pathname +
    "?" + params.toString() +
    location.hash;

URLは部品の組み合わせ

という意識で扱うと、
思わぬ事故を防げます。

Vue.js で使うときの考え方

Vue Router を使っていなくても、

  • タブ切り替え
  • フィルタ条件
  • モーダル状態

を URL に残すだけで、

  • リロードしても状態が戻る
  • URLを共有できる
  • デバッグが楽

というメリットがあります。

たとえば、こんな感じ。

mounted() {
    const params = new URLSearchParams(location.search);
    this.mode = params.get("mode") || "default";
}

初期値をURLから取る
これだけでも、かなり便利です。

URLは「画面状態の保存場所」

今回あらためて思ったのは、

URLはただの文字列じゃない

ということ。

ちゃんと考えて扱うと、

  • 状態
  • 意図
  • 再現性

が全部、URLの中に残ります。

URLSearchParams を使うことで、

  • 意図が伝わる
  • コードが短くなる
  • バグが減る

という恩恵もあります。

「なんとなく文字列操作」から
一歩進んで考えてみると、楽になります。

仕組みを用意してくれた人たちに感謝ですね。

次にやってみたいこと

  • 実際の Vue コンポーネントでの応用
  • 複数パラメータの扱い方
  • フィルタUIとの組み合わせ
  • hash と query の役割分担

このあたりは、
また別の記事でまとめたいと思います 🐒🔧

読んでくださってありがとうございました。
それではまた!