Vue Router の部品にデータを渡すには?
Vue Router は、一般的な Web サイトのように、Web ブラウザで「ページ」を指定して表示する事ができるので、Web アプリを作る場合でも便利な場合が多くなります。この記事では、Vue Router の「ページ」に相当する「部品」にデータを渡す場合にはどうすれば良いかを紹介します。
部品にデータを渡す基本的な方法
Vue の部品(子)に呼び出し元(親)からデータを渡す場合には、Vue の公式チュートリアルで学習したように「props」を使って渡します。Vue Router を利用する場合でも、Vue のデータを渡す仕組みは同じなので基本的なやり方は同じです。
ところが、Vue Router を利用する場合には、HTML 部分に直接「部品」の記述を書く必要がないので、どのようにデータを渡すのかがよくわからない場合があります。
例えば、Vite を利用して、Vue のサンプルプロジェクトを Vue Router を使う設定で作成した場合には、「HomveView」と「AboutView」の二つの「ページ」がつくられます。
この例では、「AboutView.vue」は次のような記述になっています。
// (AboutView.vue)
<template>
<div class="about">
<h1>This is an about page</h1>
</div>
</template>
<style>
@media (min-width: 1024px) {
.about {
min-height: 100vh;
display: flex;
align-items: center;
}
}
</style>
シンプルに、「This is an about page」を表示するだけです。
このページを表示するための設定は、二つです。
// (src/router/index.js)
import { createRouter, createWebHistory } from "vue-router";
import HomeView from "../views/HomeView.vue";
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: "/",
name: "home",
component: HomeView,
},
{
path: "/about",
name: "about",
// route level code-splitting
// this generates a separate chunk (About.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import("../views/AboutView.vue"),
},
],
});
export default router;
これが、Web ブラウザでリンク(URL)「/about」を入力した際の設定になります。
もう一つが、「App.vue」の設定です。
(src/App.vue)
<script setup>
import { RouterLink, RouterView } from "vue-router";
import HelloWorld from "@/components/HelloWorld.vue";
</script>
<template>
<header>
<img
alt="Vue logo"
class="logo"
src="@/assets/logo.svg"
width="125"
height="125"
/>
<div class="wrapper">
<HelloWorld msg="You did it!" />
<nav>
<RouterLink to="/">Home</RouterLink>
<RouterLink to="/about">About</RouterLink>
</nav>
</div>
</header>
<RouterView />
</template>
(*)CSS の「style」の部分は省略しています。
ここでは、実は、表示の部品「AboutView」は呼び出していません。
<RouterLink to="/about">About</RouterLink>
は、「src/router/index.js」で設定したリンク「/about」を表示するための設定を利用して、メニューの「About」がクリックされた際に表示するという仕組みになっています。
Vue の公式チュートリアルでは、「props」を利用して、「部品」にデータを渡す場合は、呼び出す際に「template」の部分で、部品側の「props」で指定した名前に対応するデータを埋め込んでデータを渡す仕組みでした。ところが、この実装では、「部品」を直接呼び出す部分は書かれていません。
部品側の書き方は同じ!
Vue Router を利用した場合は、Vue の公式チュートリアルで学習したやり方とは「何かが違う」というのはわかりました。
では、どのようにデータを渡すかを見ていくわけですが、最初に知っておくのは、「部品側の書き方」は、Vue の公式チュートリアルで学習したものと同じ書き方で良いという点です。
サンプルプロジェクトの「src/views/AboutView.vue」を少し書き換えて呼び出す際に「data」というデータを渡して、その中身を表示するようにしています。
(src/views/AboutView.vue)
<template>
<div class="about">
<h1>This is an about page</h1>
<h2>{{ "Data = " + data }}</h2>
</div>
</template>
<script>
export default {
props: ["data"],
};
</script>
<style>
@media (min-width: 1024px) {
.about {
min-height: 100vh;
display: flex;
align-items: center;
}
}
</style>
この部分で、「props」で受け取るデータ「data」を作っています。
<script>
export default {
props: ["data"],
};
</script>
この受け取ったデータを、「template」の部分の HTML の記述で
<h2>{{ "Data = " + data }}</h2>
で表示できるようにしています。
このやり方は、Vue の公式チュートリアルで学習した方法と全く同じやり方です。
しかし、このコードを実行すると、「Data = undefined」と表示されます。 つまり、データを渡す記述がないので、「undefined」(値が設定されていない)という状態になっています。
データをどうやって渡すか?
では、データを渡す部分をどのように渡せば良いかですが、これは、Vue の公式サイトで説明されています。
基本は、幾つかありますが、この記事では二つの方法について取り上げてみました。
* 固定のデータを渡す方法
* リンクで指定する方法
固定のデータを渡す方法は、Vue Router の設定、つまり「src/router/index.js」で渡す方法です。
{
path: "/about",
name: "about",
// route level code-splitting
// this generates a separate chunk (About.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import("../views/AboutView.vue"),
props: { data: "固定のデータ"}
},
のように、「props」のデータをここで書いておけばデータを渡す事ができます。
もう一つは呼び出す際に渡す方法ですが、直接部品を記述する場所がないので、Vue の公式 t フーとリアルの方法は利用できません。しかし、Web ブラウザの基本機能で、「リンクに情報を追加」する方法で渡す事ができます。
通常は、この「AboutVue」を呼び出す場合、開発用のサーバーを利用する場合は、
localhost:3000/about
のように指定しますが、これに「props」のデータを追加して指定する事ができます。
localhost:3000/about?data=add-to-link
のように指定する事でデータを渡す事が可能です。 この場合でも「src/router/index.js」に追加の記述が必要です。
{
path: "/about",
name: "about",
// route level code-splitting
// this generates a separate chunk (About.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import("../views/AboutView.vue"),
props: (route) => ({ data: route.query.data }),
},
のように、「props」の部分で「アロー関数」を使って値をセットするような記述を追加するとデータを渡せるようになります。
上のような形式で Web ブラウザにリンク(URL)を追加する際に指定する事もできますし、プログラムで指定することもできます。
<RouterLink to="/about?data=From menu">About</RouterLink>
このように、指定すると、直接部品を呼び出さないで「リンク」で指定する場合でも、データを渡す事ができるようになります。
今回のポイントは?
この記事のポイントは、Vue Router の設定で「props」を指定できるという点だけです。 部品側の作り方は、Vue の公式チュートリアルと変わりませんし、リンク上でデータを指定する方法は、Web ブラウザの基本的な機能の一つです。
Web ブラウザの基本的な機能は、Web ブラウザが Web サーバーとやり取りをする基本の仕組み( HTTP)から来ています。今回利用するのは、リンクに「?=XXXX」という書き方を追加すると、「XXXX」というデータを渡せるという仕組みを利用しています。
これは、Vue の特別な機能ではなく、Web の仕組みの一部です。 Web 開発のプログラミングの学習ではこうしたプログラミングに関係した他の Web の知識が必要になる場合も多く、こうした知識を必要に応じて身につけていく必要があるという事も今回の大きなポイントになります。
まとめ
この記事では、Vue Router を利用する場合は、一般的な Vue の部品にデータを渡す場合とは違うやり方でデータを渡す方法もあるという話を紹介しました。
色々なやり方があって、学習するのも面倒なイメージがありますが、Web の仕組みは色々なケースを想定して決められています。今回紹介した新しい学習項目の一つは「リンクにデータを埋め込む」という方法です。この仕組みは本来、Web ブラウザが Web サーバーにデータを渡す場合に利用される仕組みですが、この仕組みを利用して、Vue では、リンクに埋め込んだデータを部品に渡すのに利用しています。
プログラミングの学習に合わせて、Web の仕組みを少しづつ増やしていくと、色々なケースに対応できるエンジニアに近づく事ができます。プログラミングだけではなく、こうした機械に Web の仕組みも学習する事も、よいエンジニアに成長するためには重要です!