Vue Router — 動的ルート
テクノロジ系 / L04 routing — ルーティング
Vue Router — 動的ルート
定義
{ path: "/users/:id", component: UserDetail }:id でパラメータ。複数も OK:
{ path: "/users/:userId/posts/:postId", component: PostDetail }useRoute で取得
<script setup lang="ts">
import { useRoute } from "vue-router";
import { computed } from "vue";
const route = useRoute();
const id = computed(() => parseInt(route.params.id as string, 10));
</script>
<template>
<p>User {{ id }}</p>
</template>route.params で URL パラメータ取得。
常に string なので数値化が必要。
クエリ
<script setup> const route = useRoute(); const q = computed(() => (route.query.q as string) ?? ""); const page = computed(() => parseInt((route.query.page as string) ?? "1", 10)); </script>
/search?q=foo&page=2 → route.query.q = "foo"。
params 変化時の再 fetch
<!-- 同じコンポーネントで :id が変わると ... -->
<!-- mount は走らない (コンポーネント再利用) -->
<script setup>
import { useRoute } from "vue-router";
import { ref, watchEffect } from "vue";
const route = useRoute();
const user = ref<User | null>(null);
watchEffect(async () => {
const id = route.params.id;
if (!id) return;
user.value = await (await fetch(`/api/users/${id}`)).json();
});
</script>watchEffect で route.params.id を見ているので、URL変化で自動再 fetch。
ルートを書き換える
<script setup>
const router = useRouter();
function gotoSearch() {
router.push({ path: "/search", query: { q: "foo", page: 2 } });
}
function updateQuery() {
router.push({ query: { ...router.currentRoute.value.query, page: 3 } });
}
</script>object 形式で書ける。
クエリ更新で履歴に積まないなら router.replace(...)。
ルート名で遷移
const routes = [
{ path: "/users/:id", component: UserDetail, name: "user-detail" },
];
router.push({ name: "user-detail", params: { id: 1 } });name で参照すれば URL 構造変更に強い。
まとめ
:idで動的セグメントuseRoute().params.idで取得 (string)- params 変化は 同じコンポーネント再利用 なので watch で再 fetch
router.push({ name, params, query })で型安全に近い遷移router.replaceは履歴に積まない
次は ネストルート。
考えてみよう
既定では正解・不正解の判定はしません。自分のペースで「答えを見る」を。採点してほしい場合だけ「採点してほしい」を押してください。
Lv1: 基本 — useRoute
問題
// router
{ path: "/users/:id", component: UserDetail }<!-- UserDetail.vue -->
<script setup lang="ts">
import { useRoute } from "vue-router";
import { computed } from "vue";
const route = useRoute();
const id = computed(() => parseInt(route.params.id as string, 10));
</script>
<template>
<p>User ID: {{ id }}</p>
</template>合格基準
/users/1 → "User ID: 1"
Lv2: 応用 — params 変化時の watchEffect
問題
<script setup lang="ts">
import { useRoute } from "vue-router";
import { ref, watchEffect } from "vue";
const route = useRoute();
const user = ref<any>(null);
watchEffect(async () => {
const id = route.params.id;
if (!id) return;
user.value = null;
const res = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`);
user.value = await res.json();
});
</script>
<template>
<pre>{{ user }}</pre>
</template>URL を /users/1 → /users/2 と変えると 同じ component 内で 再fetch。
合格基準
- 同じ component 再利用
- watchEffect で自動再取得
Lv3: 発展 — 検索クエリ
問題
<script setup>
import { useRoute, useRouter } from "vue-router";
import { computed } from "vue";
const route = useRoute();
const router = useRouter();
const q = computed(() => (route.query.q as string) ?? "");
const page = computed(() => parseInt((route.query.page as string) ?? "1", 10));
function updateQ(v: string) {
router.push({ query: { ...route.query, q: v, page: "1" } });
}
</script>
<template>
<input :value="q" @input="updateQ(($event.target as HTMLInputElement).value)" />
<p>q={{ q }}, page={{ page }}</p>
</template>URL バーに ?q=...&page=... が反映される。
合格基準
- 検索文字が URL に同期
- ブックマーク・共有可能
提出
submission.md に3問の回答を。