こんにちは、コンスキです。
今回は、フック関数とナビゲーションガードというものについて説明します。
フック関数とナビゲーションガードとは
Vue Routerのフック関数とは、router-link要素をクリックして「ページ遷移」が行われるタイミングをフックにして、処理を行う関数のことです。
実際は表示内容が変更されているだけで「ページ遷移」は行われていませんが、表示内容がルーティングされて表示内容が変更されることを指して「ページ遷移」と言っています。
このようなフック関数を使って、特定の条件のときにページにページ遷移させない、または、違うページにページ遷移させることをナビゲーションガードといいます。
フック関数はナビゲーションガードとして、リダイレクトを行う際などに使うことができます。
例えば、現在は使用されていないページへページ遷移が行われたタイミングをフックとして、現在使用されているページへ強制的にページ遷移し直すような「リダイレクト」を行うことができます。
フックの種類
Vueインスタンスのライフサイクルフックにも、フックとなるタイミングに種類がありました。
Vue Routerのフックにも、同じようにフックとなるタイミングに種類がありますが、Vue Routerのフックの場合、すべてのページにおける、ページ遷移時に有効なフックと、特定のルートや特定のコンポーネントへページ遷移した時のみ、またはそれらからページ遷移してきた時のみに有効なフックがあります。
すべてのページにおける、ページ内容の変更時に有効なフック
フックの種類 | 関数が実行されるタイミング |
---|---|
beforeResolve | あるページにページ遷移が行われる直前 |
afterEach | あるページからページ遷移が行われた直後 |
特定ルートにおける、ページ内容の変更時に有効なフック
フックの種類 | 関数が実行されるタイミング |
---|---|
beforeEnter | あるページにページ遷移が行われる直前 |
特定のコンポーネントにおける、ページ内容の変更時に有効なフック
フックの種類 | 関数が実行されるタイミング |
---|---|
beforeRouteEnter | あるページにページ遷移が行われる直前 |
beforeRouteUpdate | 同じコンポーネントへページ遷移が行われる直前 |
beforeRouteLeave | あるページからページ遷移が行われた直後 |
フック関数の使い方
次の3つのフック関数では、to、from、nextの3つの引数を取ります。
toはページ遷移先のルートのオブジェクトで、fromはページ遷移元のルートのオブジェクトです。
nextはページ遷移を行う関数で、引数にページ遷移先のルートオブジェクトのpathが入ります。next関数を記述しないと、ページ遷移がずっと終わらなくなってしまうので、必ず記述する必要があります。
すべてのページにおける、ページ内容の変更時に有効なフック関数
var router = new VueRouter({
//ここにroutesプロパティを設定します
})
router.フックの名前(function (to, from, next) {
//ここにフック関数の処理を書来ます
})
例えば、現在使用していないページへページ遷移した場合、ページが移転されたことを知らせるページへリダイレクトするようなプログラムは次のようになります。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>ナビゲーションガード</title>
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head>
<body>
<div id="app">
<router-link to="/page1">ページ1を表示</router-link>
<router-link to="/newPage2">ページ2を表示</router-link>
<router-link to="/oldPage2">ページ2を表示</router-link>
<router-view></router-view>
</div>
<script>
var Relocated = {
template: `
<div>
<h1>このページは移転されました。</h1>
<router-link to="/newPage2">新しいページ2を表示</router-link>
</div>
`
}
var router = new VueRouter({
routes: [
{
path: '/page1',
component: {
template: '<h1>ページ1です。</h1>'
}
},
{
path: '/newPage2',
component: {
template: "<h1>ページ2です。</h1>"
}
},
{
path: '/oldPage2',
component: {
template: "<h1>旧ページ2です。</h1>"
}
},
{
path: '/relocated',
component: Relocated
}
]
})
router.beforeEach(function (to, from, next) {
if (to.path === "/oldPage2") { //ページ遷移先のルートのpathが"/oldPage2"だった時に移転されたことを知らせる
next("/relocated") //ページにリダイレクトします
} else {
next() //それ以外のページ遷移は普通に行います
}
})
var vm = new Vue({
el: "#app",
router: router
})
</script>
</body>
</html>
ブラウザには次のように表示されます。
ページ2へのリンクが2つあり、右の方は古いページ2へのリンクになっています。古いページ2へページ遷移しようとすると、移転を知らせるページヘリダイレクトされます。
特定ルートにおける、ページ内容の変更時に有効なフック関数
var router = new Vue Router({
var lroutes = [
{
path: "このルートのURL",
component: {
template: "コンポーネントの内容"
}
フックの名前: function () {
//ここにフック関数の処理を書きます
}
}
]
})
特定のコンポーネントにおける、ページ内容の変更時に有効なフック関数
var コンポーネント名 = {
template: "コンポーネントの内容",
フックの名前: function () {
//ここにフック関数の処理を書きます
}
}
var router = new Vue Router({
var routes = [
{
path: "このルートのURL",
component: コンポーネント名
}
]
})
例えば、ページの内容が保存されずに、ページ遷移が行われたときに、ページの遷移をキャンセルして、警告を出すプログラムは次のようになります。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>ナビゲーションガード</title>
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head>
<body>
<div id="app">
<router-link to="/page1">ページ1を表示</router-link>
<router-link to="/page2">ページ2を表示</router-link>
<router-link to="/page3">ページ3を表示</router-link>
<router-link to="/page4">ページ4を表示</router-link>
<router-link to="/page5">ページ5を表示</router-link>
<router-link to="/page6">ページ6を表示</router-link>
<router-view></router-view>
</div>
<script>
var Page2 = {
template: `
<div>
<h1>ページ2です。</h1>
<textarea rows="4" cols="40"></textarea>
<br>
<button v-on:click="save()">{{ button }}</button>
<p>保存状態:{{ displayState }}</p>
</div>
`,
data: function () {
return {
button: "保存する",
isSaved: false,
}
},
computed: {
displayState: function () {
if (!this.isSaved) {
return "保存されていません。"
} else {
return "保存済みです。"
}
}
},
methods: {
save: function () {
this.isSaved = true
}
},
beforeRouteLeave: function (to, from, next) {
if (!this.isSaved) {
alert("内容がまだ保存されていません。")
next(false)
} else {
next()
}
}
}
var router = new VueRouter({
routes: [
{
path: '/page1',
component: {
template: '<h1>ページ1です。</h1>'
}
},
{
path: '/page2',
component: Page2
},
{
path: '/page3',
component: {
template: "<h1>ページ3です。</h1>"
}
},
{
path: '/page4',
component: {
template: "<h1>ページ4です。</h1>"
}
},
{
path: '/page5',
component: {
template: "<h1>ページ5です。</h1>"
}
},
{
path: '/page6',
component: {
template: "<h1>ページ6です。</h1>"
}
}
]
})
var vm = new Vue({
el: "#app",
router: router
})
</script>
</body>
</html>
ブラウザに表示すると次のようになります。
はじめは、6つのページヘのリンクがあります。「ページ2を表示」をクリックしてページ2へページ遷移して下さい。
すると次のようなテキストエリアとボタン、保存状態が表示されます。
「保存する」というボタンを押さずに他のページへのページ遷移を行おうとすると、ページ遷移は行われず、警告が出ると思います。
まとめ
- Vue Routerのフック関数は、ページ遷移が行われるタイミングに実行される関数
- 特定の条件のときに、ページ遷移をキャンセルあるいはリダイレクトさせることをナビゲーションガードという
- フック関数には、グローバルなフック関数、ルート単位のフック関数、コンポーネント単位でのフック関数がある
コメント