Vue Routerの基本と高度な使い方

原理

ボタンクリック/ルートトリガー → パス変更 → routerによる検知 → router/index.jsの設定ルールに基づき対応ページへ遷移

基本的な使用法

  1. 対応するSPAコンポーネント(vueページ)を作成

---AboutPage.vue---
<template>
    <h2>Aboutページのコンテンツ</h2>
</template>

<script>
    export default {
        name: 'AboutPage'
    }
</script>

---HomePage.vue---
<template>
    <h2>Homeページのコンテンツ</h2>
</template>

<script>
    export default {
        name: 'HomePage'
    }
</script>
  1. router/index.js内でアプリケーション全体のルーターを作成

-- router/index.js --
// このファイルはアプリケーション全体のルーター作成専用
import VueRouter from 'vue-router'
// コンポーネントのインポート
import AboutPage from '../components/AboutPage'
import HomePage from '../components/HomePage'

// ルーターの作成とエクスポート
export default new VueRouter({
    routes: [
        {
            path: '/about',
            component: AboutPage
        },
        {
            path: '/home',
            component: HomePage
        }
    ]
})
  1. main.jsでvue-routerプラグインをインポート・使用し、ルーターrouter/index.jsをインポート、作成されたvmにrouterを追加

--main.js --
// Vueのインポート
import Vue from 'vue'
// Appのインポート
import App from './App.vue'
// VueRouterのインポート
import VueRouter from 'vue-router'
// ルーターのインポート
import router from './router'

// Vueのプロダクションヒントを無効化
Vue.config.productionTip = false
// プラグインの適用
Vue.use(VueRouter)

// vmの作成
new Vue({
    el: '#app',
    render: h => h(App),
    router: router
})
  1. 遷移の実装
    ルートをトリガーする場所でrouter-linkを使用して遷移コンポーネントを指定し、router-viewでコンポーネントの表示位置を指定

<div class="row">
  <div class="col-xs-2 col-xs-offset-2">
    <div class="list-group">
        
        <router-link active-class="active" to="/about">About</router-link>
        <router-link active-class="active" to="/home">Home</router-link>
    </div>
  </div>
  <div class="col-xs-6">
    <div class="panel">
      <div class="panel-body">
        
        <router-view></router-view>
      </div>
    </div>
  </div>
</div>

ネストされたルート

ネストされたルートでは、最初のレベルのpathの前にのみ/を追加します


-- router/index.js --
// このファイルはアプリケーション全体のルーター作成専用
import VueRouter from 'vue-router'
// コンポーネントのインポート
import AboutPage from '../pages/AboutPage'
import HomePage from '../pages/HomePage'
import NewsPage from '../pages/NewsPage'
import MessagePage from '../pages/MessagePage'

// ルーターの作成とエクスポート
export default new VueRouter({
    routes: [
        {
            path: '/about',
            component: AboutPage
        },
        {
            path: '/home',
            component: HomePage,
            children: [
                {
                    path: 'news',
                    component: NewsPage,
                },
                {
                    path: 'message',
                    component: MessagePage,
                }
            ]
        }
    ]
})

router-linkのパスが2次ルートの場合、親ページのアドレスも含める必要があります


---HomePage.vue---
<template>
    <div>
        <h2>Homeコンポーネントのコンテンツ</h2>
        <div>
            <ul class="nav nav-tabs">
                <li>
                    <router-link class="list-group-item" active-class="active" to="/home/news">News</router-link>
                </li>
                <li>
                    <router-link class="list-group-item" active-class="active" to="/home/message">Message</router-link>
                </li>
            </ul>
            <router-view></router-view>
        </div>
    </div>
</template>

<script>
    export default {
        name: 'HomePage',
    }
</script>

ルートパラメータの受け渡し

クエリパラメータ

クエリを介してパラメータを渡す場合、パラメータはアドレスバーに表示されます
親コンポーネントは<router-link>で値を渡します
:toの値をオブジェクト形式で記述し、query属性でパラメータを渡す方法、または:toに直接パラメータ形式で記述する方法があります


<template>
    <div>
        <ul>
            <li v-for="item in messageItems" :key="item.id">
                
                <!-- <router-link :to="`/home/message/detail?id=${item.id}&title=${item.title}`">{{item.title}}</router-link>   -->

                
                <router-link :to="{
                    path: '/home/message/detail',
                    query: {
                        id: item.id,
                        title: item.title
                    }
                }">
                    {{item.title}}
                </router-link>
            
            </li>
        </ul>
        <hr>
        <router-view></router-view>
    </div>
</template>

<script>
    export default {
        name: 'MessagePage',
        data() {
            return {
                messageItems: [
                    {id: '001', title: 'メッセージ001'},
                    {id: '002', title: 'メッセージ002'},
                    {id: '003', title: 'メッセージ003'}
                ]
            }
        },
    }
</script>

子コンポーネントでのパラメータ受け取り


<template>
    <ul>
        <li>メッセージID:{{$route.query.id}}</li>
        <li>メッセージタイトル:{{$route.query.title}}</li>
    </ul>
</template>

<script>
    export default {
        name: 'DetailPage',
        mounted() {
            console.log(this.$route)
        },
    }
</script>

パラメータ

ルート設定時にプレースホルダを使用してパラメータを宣言します


{
    path: 'message',
    component: MessagePage,
    children: [
        {
            name: 'detail',
            path: 'item/:id/:title',
            component: DetailPage,
        }
    ]
}

パラメータの渡し方



   <router-link :to="/home/message/detail/666/こんにちは">移動</router-link>
                
   
   <router-link 
    :to="{
        name: 'detail',
        params: {
            id: 666,
            title: 'こんにちは'
        }
    }"
   >移動</router-link>

パラメータの受け取り方


<template>
    <ul>
        <li>メッセージID:{{$route.params.id}}</li>
        <li>メッセージタイトル:{{$route.params.title}}</li>
    </ul>
</template>

Props

ルート設定


// ルーターの作成とエクスポート
export default new VueRouter({
    routes: [
        {
            name: 'about',
            path: '/about',
            component: AboutPage
        },
        {
            path: '/home',
            component: HomePage,
            children: [
                {
                    path: 'news',
                    component: NewsPage,
                },
                {
                    path: 'message',
                    component: MessagePage,
                    children: [
                        {
                            name: 'detail',
                            path: 'item',
                            component: DetailPage,

                            // Propsの第一の記述法、値はオブジェクト、オブジェクトのすべてのkey-valueがpropsとしてDetailコンポーネントに渡されます。
                            // props: {a: 1, b: 'hello'}

                            // Propsの第二の記述法、値は真偽値、真の場合、そのルートコンポーネントが受け取るすべてのparamsパラメータをpropsとしてDetailコンポーネントに渡します。
                            // props: true

                            // Propsの第三の記述法、値は関数
                            props($route) {
                                return {
                                    id: $route.query.id,
                                    title: $route.query.title,
                                }
                            }
                        }
                    ]
                }
            ]
        }
    ]
})

パラメータの渡し方


<template>
    <div>
        <ul>
            <li v-for="item in messageItems" :key="item.id">
                <router-link :to="{
                    name: 'detail',
                    query: {
                        id: item.id,
                        title: item.title
                    }
                }">
                    {{item.title}}
                </router-link>
            
            </li>
        </ul>
        <hr>
        <router-view></router-view>
    </div>
</template>

<script>
    export default {
        name: 'MessagePage',
        data() {
            return {
                messageItems: [
                    {id: '001', title: 'メッセージ001'},
                    {id: '002', title: 'メッセージ002'},
                    {id: '003', title: 'メッセージ003'}
                ]
            }
        },
    }
</script>

パラメータの受け取り方


<template>
    <ul>
        <li>メッセージID:{{itemId}}</li>
        <li>メッセージタイトル:{{itemTitle}}</li>
    </ul>
</template>

<script>
    export default {
        name: 'DetailPage',
        props: ['itemId', 'itemTitle'],
    }
</script>

Replaceモード

replace属性は、ルート遷移時にブラウザの履歴操作モードを制御できます
ブラウザの履歴には2種類の書き込み方式があります:pushreplace。pushは履歴を追加します(閲覧したURLリクエストをスタックにプッシュ)、replaceは現在のレコードを置き換えます(スタックトップのURLリクエストを置き換えます)。デフォルトはpushモードです。pushモードでは戻ると進むが可能ですが、replaceモードではできません。


<router-link replace active-class="active" to="/home/news">News</router-link>

プログラムによるルーティング

this.$router.pushのパラメータ記述法は<router-link>と同じです


<template>
    <div>
        <ul>
            <li v-for="item in messageItems" :key="item.id">
                <button @click="pushDisplay(item)">pushで表示</button>
                <button @click="replaceDisplay(item)">replaceで表示</button>
            </li>
        </ul>
        <hr>
        <router-view></router-view>
    </div>
</template>

<script>
    export default {
        name: 'MessagePage',
        data() {
            return {
                messageItems: [
                    {id: '001', title: 'メッセージ001'},
                    {id: '002', title: 'メッセージ002'},
                    {id: '003', title: 'メッセージ003'}
                ]
            }
        },
        methods: {
            pushDisplay(item){
                this.$router.push({
                    name: 'detail',
                    query: {
                        id: item.id,
                        title: item.title
                    }
                })
            },
            replaceDisplay(item){
                this.$router.replace({
                    name: 'detail',
                    query: {
                        id: item.id,
                        title: item.title
                    }
                })
            }
        },
    }
</script>

パラメータ受け取りの記述法は変更ありません

Keep-alive

keep-aliveコンポーネントは、その間に挟まれたコンポーネントの切り替え過程で状態をメモリに保持し、DOMの再描画を防ぎます

基本的な使用法


<keep-alive include="NewsPage">
    <router-view></router-view>
</keep-alive>

Include

デフォルトでは<keep-alive>内のすべてのコンポーネントがキャッシュされますが、includeでキャッシュ対象のコンポーネントを指定できます。ここでの名前はコンポーネントの名前です



<keep-alive :include="['NewsPage', 'MessagePage']">
    <router-view></router-view>
</keep-alive>


<keep-alive include="NewsPage">
    <router-view></router-view>
</keep-alive>

ActivatedとDeactivated

keep-aliveキャッシュが設定されたコンポーネントは、2つの追加のライフサイクルフックが利用できます:activateddeactivated
以下のような機能を実現したい場合、これらのフックが使用できます:コンポーネントがバックグラウンドからフォアグラウンドに切り替わったとき(activated)に何か処理を行い、バックグラウンドに切り替わった後(deactivated)に処理を停止する場合

ルートガード

ルート切り替え前と切り替え後に表示され、ページ切り替え時の権限検証に使用できます

グローバルガード

beforeEach & afterEach

// グローバルルートガード——初期化時に呼び出され、各ルート切り替え前に呼び出される
router.beforeEach((to, from, next) => {
    // ルートに移動する必要がある場合
    if (to.meta.isAuth) {
        // schoolがローカルストレージで'qinghuadaxue'の場合、アクセス可能
        if (localStorage.getItem('school') === 'qinghuadaxue') {
            next()  // 通過許可
        } else {
            alert('申し訳ありません、アクセス権限がありません!')
        }
    } else {
        // それ以外は通過許可
        next()
    }
})

// グローバル後置ルートガード——初期化時に呼び出され、各ルート切り替え後に呼び出される
router.afterEach((to, from) => {
    document.title = to.meta.title || 'デフォルト名'    // ページのtitleを変更
})

その他

  • <keep-alive>で囲まれていない場合、ルート切り替え後、以前のコンポーネントは破棄されます
  • vmインスタンスには2つの属性$route$routerがあります。前者は現在のルート情報、後者はアプリケーション全体のルートです

タグ: Vue Vue Router フロントエンド ルーティング SPA

7月2日 22:12 投稿