Vue Router 3のthis.$route.queryでクエリパラメータは取れるけど、lazy loadingだと取れないことがあるらしい

  • Vue.js
  • Vue Router

この記事は、構成と文章の整理にAIを使っています。
あくまで読みやすくするための補助で、内容そのものをAIにすべて任せて書いているわけではありませんが、ところどころ相談しながら整えています。

Vue.js 2 + Vue Router 3でクエリパラメータを取るなら this.$route.query を見ればいい。ただしルートをlazy loadingしている構成だと、createdフックの時点でqueryが空になることがあるらしい。挙動が怪しいと思ったらまずここを疑う。

基本の取り方

Vue Routerでルートを定義しておけば、コンポーネント側は this.$route.query にアクセスするだけでいい。

import Vue from 'vue';
import Router from 'vue-router';
import ExamplePage from './components/ExamplePage.vue';
Vue.use(Router);
export default new Router({
routes: [
{
path: '/example',
name: 'ExamplePage',
component: ExamplePage,
},
],
});

コンポーネント側はこう。

<template>
<div>
<p>ID: {{ $route.query.id }}</p>
</div>
</template>
<script>
export default {
name: 'ExamplePage',
mounted() {
console.log(this.$route.query.id);
},
};
</script>

params と混同しがちだけど、?id=1 みたいなクエリ文字列は query、/users/:id みたいな動的セグメントは params。別物として覚えておく。

lazy loadingだと危ういケース

ルートをlazy loadingしている場合(component: () => import('./ExamplePage.vue') みたいなやつ)、App.vue の created フックの時点で this.$route.query を見ると空になるという報告がVue RouterのGitHub issueに上がっている。

再現条件として挙げられていたのは以下。

  • vue-cliでプロジェクトを作ってvue-routerを導入
  • App.vue の created で this.$route.query をログ出力
  • lazy loadedなルートに直接アクセス(例: /#/about?tiers=xxx)

このケースだとqueryが取れず、逆にトップページ(/#/?tiers=xxx)だと取れる、という切り分けがされていた。実機未確認だけど、lazy loadingを使っていて App.vue レベルでqueryに依存した初期化処理を書いている場合は要注意かもしれない。個別コンポーネントの mounted や created で見る分には基本問題にならないはず。

まとめると

  • 通常のコンポーネント内でクエリを取るだけなら this.$route.query で十分
  • App.vue などのルート直下でlazy loadedなルートのqueryに依存する処理を書くなら、タイミングに注意した方がいい