Vue Routerで遷移先にデータを渡す方法を解説します。
要件
画面はトップページとメニューページの2つで、それぞれコンポーネント化しており、兄弟関係です。
メニューページには商品があり、カテゴリーを選択すると商品が絞り込まれます。初期設定ではすべての商品が表示されています。
トップページからメニューページに遷移するには、そのままメニューへのリンクを踏むか、カテゴリーリンクを踏むかの2つの方法があります。
今回、遷移先に渡したいデータは、「どのカテゴリーリンクを踏んだのか」です。
それによって遷移先のメニューページで、カテゴリーに絞った商品を表示することができます。
開発環境
今回はVue + Vue CLI + Vue Routerを使用しています。
バージョン
Vue.js 2.6.11 (npm list vue)
Vue CLI 4.2.3 (vue –version)
Vue Router 3.1.6 (npm list vue-router)
Node.js 12.10.0 (node -v)
ディレクトリ構造
src/
│├components/
││ ├Header.vue
││ ├Home.vue
││ └Menu.vue
│└App.vue
├main.js
└router.js
こんな感じです。Header.vueにはナビメニューがあり、トップページとメニューページへの行き来が可能です。
各ファイルの中身
では、各ファイルの中身を見ていきましょう。
router.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from './components/Home'
import Shop from './components/Shop'
Vue.use(VueRouter)
const routes = [
{
path: '/',
component: Home,
},
{
path: '/menu',
component: Menu,
name: 'Menu', // あとでnameでリンク先を指定する
props: true
}
]
const router = new VueRouter({
mode: 'history',
routes,
scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return savedPosition;
} else {
return {
x: 0,
y: 0
};
}
}
})
export default router
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
router
}).$mount('#app')
むむ…とくに解説することがないぞ
App.vue
<template>
<div id="app">
<Header />
<router-view></router-view> // ここにHome.vueやMenu.vueが表示される
</div>
</template>
<script>
import Header from "./components/Header";
export default {
name: "App",
components: {
Header
}
};
</script>
うん。
Header.vue
<template>
<header>
<nav>
<ul>
<li>
<router-link to="/" exact>HOME</router-link>
</li>
<li>
<router-link to="/about">ABOUT</router-link>
</li>
<li>
<router-link to="/menu">MENU</router-link>
</li>
<li>
<router-link to="/contact">CONTACT</router-link>
</li>
</ul>
</nav>
</header>
</template>
<script>
export default {};
</script>
Homeコンポーネントへのrouter-linkにexactをつけているのは、activeクラスの関係です。ここでは関係ないので省略します。
ナビメニューのMENUからMenuコンポーネントを表示したときは、すべての商品が表示されます。
Home.vue
<template>
<section>
//色々と省略してカテゴリーのrouter-linkのみ
<router-link :to="{name:'Menu', params:{'selectedCategory':'dessert'}}">
Desserts
</router-link>
<router-link :to="{name:'Menu', params:{'selectedCategory':'beverage'}}">
Beverages
</router-link>
</section>
</template>
<script>
export default {};
</script>
router-linkのtoに先ほどroutesの中で定義したnameを指定します。Menuコンポーネントを表示したいので’Menu’ですね。
paramsには、Menuコンポーネントに渡したいデータをkey:valueで指定します。
Dessertsをクリックするとデザートのみが、Beveragesをクリックするとドリンクのみが表示されます。
Menu.vue
<template>
<div>
// カテゴリー選択ボタン
<div>
<input
type="radio"
name="category"
id="all"
value="all"
v-model="category"
checked // 初期設定
@change="changeCategory"
/>
<label for="all">ALL</label>
<input
type="radio"
name="category"
id="desserts"
value="desserts"
v-model="category"
@change="changeCategory"
/>
<label for="desserts">Desserts</label>
<input
type="radio"
name="category"
id="beverages"
value="beverages"
v-model="category"
@change="changeCategory"
/>
<label for="beverages">Beverages</label>
</div>
// 商品一覧レンダリング
<ul>
<li v-for="item in selectedItems" :key="item.id">
{{item.title}}
</li>
</ul>
</div>
</template>
<script>
import items from "@/assets/item"; // 別のファイルで管理している商品リストを読み込む
export default {
name: "Items",
props: ["selectedCategory"], // 選択されたカテゴリーを受け取る
data() {
return {
category: "all", //ナビメニューで「MENU」を押したときの初期設定
items,
selectedItems: []
};
},
methods: {
changeCategory() {
// カテゴリーを変更するごとに商品リストの内容を入れ替える処理
},
mounted() {
// Menuコンポーネントが表示されるときの処理
let tempBox = [];
if (this.selectedCategory) { // Homeページからカテゴリーを選んで遷移してきたとき
this.category = this.selectedCategory;
for (var i = 0; i < this.items.length; i++) {
if (this.items[i].category === this.category) {
tempBox.push(this.items[i]);
}
}
} else {
tempBox = this.items; // HomeページからMENUを押して遷移してきたとき
}
this.selectedItems = tempBox;
}
};
</script>
本当はfor文で回すよりもfindで該当のitemを見つけてpushした方がスマートなのですが、core-js関連のエラーが出てめんどくさくなったのでforを使いました。
が、後日別のメソッドでもcore-jsのエラーが出たので、結局babel.config.jsの書き換えを行っています。同じようにエラーのある方は下記ご参照ください。
参照:https://github.com/vuejs/vue-cli/issues/3678
<router-link>の内容を詳しく解説
Home.vueからMenu.vueへの<router-link>には、toでコンポーネントの名前とparamsを渡しています。
<router-link :to="{name:'Menu', params:{'selectedCategory':'dessert'}}">
Desserts
</router-link>
これは、このリンクを踏むとMenu.vueコンポーネントを表示し、selectedCategoryにdessertという値を与えましたよという意味です。
遷移先であり受け取り側でもあるMenu.vueでは、propsでsetectedCategoryの値を受け取ります。
props: ["selectedCategory"]
とても簡単ですね!
Vueを初めて触ったときは、それでいっぱいいっぱいだったのでVue Routerのことなんてきちんと学ぶ余裕がありませんでした。
でも今ではVue Routerの便利さと使いやすさがとてもわかります。
今はまだむずかしいなと感じる方でも、しっかりひとつひとつ分析していくとわかってくるので大丈夫ですよ!このブログが少しでも助けになると光栄です。