もがき系プログラマの日常

もがき系エンジニアの勉強したこと、日常のこと、気になっている技術、備忘録などを紹介するブログです。

Vue.js入門 基礎から実践アプリケーション開発までを読んだ vol.4

はじめに

こんにちは。

Kojirockの1人アドベントカレンダー Advent Calendar 2018の4日目の記事です。

以下の本を読んで勉強できたことを記載していきます。

今回は第4章です。

Vue.js入門 基礎から実践アプリケーション開発まで

Vue.js入門 基礎から実践アプリケーション開発まで

4章 Vue Routerを活用したアプリケーション開発

目次

4.1 Vue Routerによるシングルページアプリケーション

4.2 ルーティングの基礎

4.3 実践的なルーティングのための機能

4.4 サンプルアプリケーションの実装

4.5 Vue Routerの高度な機能

4.1 Vue Routerによるシングルページアプリケーション

こちらでは、Vue Routerの概要を紹介してくれています。

簡単な使い方としては、以下のような定義です。

new VueRouter({
    routes: [
        {
            path: '/profile',
            component: Profile
        },
        {
            path: '/about',
            component: About
        }
    ]
})

該当するpathに応じて指定したコンポーネントを表示するという具合のようです。

その他の便利な機能があるので、この後出てくることを期待しておきます。

ちなみに、自分はSPAのwebアプリケーション開発は経験あるのですが、残念ながらバックエンド側だったので、フロントエンド側はノータッチでした。

この辺は興味津々です。

4.2 ルーティングの基礎

こちらでは、前述したRouterの簡単な定義を使用して、実際に動くものの紹介がありました。

<!DOCTYPE html>
<html>
<head>
    <title>Page Title</title>
    <script src="https://unpkg.com/vue@2.5.17"></script>
    <script src="https://unpkg.com/vue-router@3.0.1"></script>
</head>
<body>
    <div id="app">
        <router-link to="/">トップページ</router-link>
        <router-link to="/news">ニュース</router-link>
        <router-link to="/profile">プロフィール</router-link>
        <router-view></router-view>
    </div>

    <script>
        const router = new VueRouter({
            routes: [
                {
                    path: '/',
                    component: {
                        template: '<div style="background:red;">トップページ</div>'
                    }
                },
                {
                    path: '/news',
                    component: {
                        template: '<div style="background:green;">ニュースページ</div>'
                    }
                },
                {
                    path: '/profile',
                    component: {
                        template: '<div style="background:yellow;">プロフィールページ</div>'
                    }
                }
            ]
        })

        new Vue({
            el: '#app',
            router: router
        })
    </script>
</body>
</html>

f:id:kojirooooocks:20181203053013g:plain

<router-link to="xxxx"> でroutesに定義したpathを定義することで、リンクを表示することが出来ます。

componentが差し込まれる部分は <router-view> です。

4.3 実践的なルーティングのための機能

URLパラメータ

/user/1 のようなURLで user_id=1 のユーザー情報を取得したりするような場合、Vue Routerではどのように実現するかを述べてくれています。

以下のような感じで対応します。

<!DOCTYPE html>
<html>
<head>
    <title>Page Title</title>
    <script src="https://unpkg.com/vue@2.5.17"></script>
    <script src="https://unpkg.com/vue-router@3.0.1"></script>
</head>
<body>
    <div id="app">
        <ul>
            <li><router-link to="/">トップページ</router-link></li>
            <li><router-link to="/news/1">メンテンナスのお知らせ</router-link></li>
            <li><router-link to="/news/2">イベント開始</router-link></li>
            <li><router-link to="/news/3">あけましておめでとうございます</router-link></li>
        </ul>
        <router-view></router-view>
    </div>

    <script>
        const newsComponent = Vue.extend({
            template: `
                <div style="background:skyblue;">
                    <h3>こちらはID: {{ $route.params.newsId }} のニュースです</h3>
                    <p v-if="$route.params.newsId == 1">メンテナンス開始しますよ!アクセスできないですよ</p>
                    <p v-else-if="$route.params.newsId == 2">新イベントが開始されますよ!楽しんでね☆</p>
                    <p v-else-if="$route.params.newsId == 3">あけましたね!正月イベントもうすぐはじまるよ!</p>
                </div>
            `
        })

        const router = new VueRouter({
            routes: [
                {
                    path: '/',
                    component: {
                        template: '<div style="background:red;">トップページ</div>'
                    }
                },
                {
                    path: '/news/:newsId',
                    component: newsComponent
                },
            ]
        })

        new Vue({
            el: '#app',
            router: router
        })
    </script>
</body>
</html>

f:id:kojirooooocks:20181203053049g:plain

対応は簡単で、routesのpathでURLパラメータを渡す値を:で指定します。今回の例だと /news/:newsId です。

URLから与えられた値は、 $route.params から、pathで指定した名前のまま取得できいます。 今回の例だと $route.params.newsId です。

名前付きルート

指定のルートに名前を付けられます。

前述のコードのいち部を抜粋します。

{
    path: '/news/:newsId',
    name: 'news',
    component: newsComponent
},
<ul>
    <li><router-link to="/">トップページ</router-link></li>
    <li><router-link :to="{ name: 'news', params: { newsId: 1 }}">メンテンナスのお知らせ</router-link></li>
    <li><router-link :to="{ name: 'news', params: { newsId: 2 }}">イベント開始</router-link></li>
    <li><router-link :to="{ name: 'news', params: { newsId: 3 }}">あけましておめでとうございます</router-link></li>
</ul>

↑のコードは、URLパラメータで記載したコード同じ動きを実現します。

router.pushでの遷移

<router-link> を使わずに遷移することも出来ます。

何らかのアクション後、自動的に遷移されるような場合に使いそうです。

new Vue({
    el: '#app',
    router: router,
    methods: {
        linkTo: (newsId) => {
            router.push({ name: 'news', params: { newsId: newsId }})
        }
    }
})
<ul>
    <li><button v-on:click="linkTo(1)">ニュースID_1のページへ</button></li>
    <li><button v-on:click="linkTo(2)">ニュースID_2のページへ</button></li>
    <li><button v-on:click="linkTo(3)">ニュースID_3のページへ</button></li>
</ul>

f:id:kojirooooocks:20181203053130g:plain

フック

ページ遷移前後にフックを差し込めるようです。

グローバルのフック関数

全ページ遷移に設定できるフックで、 router.beforeEach でフックを差し込めます。

router.beforeEach((to, from, next) => {
    if (to.name === 'news') {
        alert('ニュースページへ遷移します')
    }
    next() ← これを実行しなれば、ページ遷移が実行されない
})
ルート単位のフック関数

特定のルート単位でフックを差し込む方法です。

routesで定義する際に指定します。

{
    path: '/news/:newsId',
    name: 'news',
    component: newsComponent,
    beforeEnter: (to, from, next) => {
        if (to.name === 'news') {
            alert('ニュースページへ遷移します')
        }
        next()                        
    }
}

4.4 サンプルアプリケーションの実装

こちらでは、Vue Routerの機能を使って、実際にサンプルのSPAを実装します。

こちらは写経させてもらいました。

f:id:kojirooooocks:20181203053208g:plain

今回、使った新たなものとしては、ライフサイクルの created を使用しています。

created以前の記事でも紹介している通り、インスタンスが生成され、データが初期化された後に実行されます。

ユーザー一覧遷移した際のcreated

created: function() {
    this.fetchData()
},
methods: {
    fetchData: function() {
        this.loading = true
        getUsers(((err, users) => {
            this.loading = false
            if (err) {
                this.error = err.toString()
            } else {
                this.users = users
            }
        }).bind(this))
    }
}

また、watch オプションを使用しています。

watch: {
    '$route': 'fetchData'
},

'$route' の変更をwatchして、ルーティングの変更に伴いfetchData()が実行されるようになります。

4.5 Vue Routerの高度な機能

サンプルアプリケーションで使用されてなかったVue Routerのその他の機能が紹介されています。

便利そうだったのは、ネストしたルーティングでした。

<!DOCTYPE html>
<html>
<head>
    <title>Page Title</title>
    <script src="https://unpkg.com/vue@2.5.17"></script>
    <script src="https://unpkg.com/vue-router@3.0.1"></script>
</head>
<body>
    <div id="app">
        <ul>
            <li><router-link to="/user/1">ユーザーID: 1</router-link></li>
            <li><router-link to="/user/2">ユーザーID: 2</router-link></li>
            <li><router-link to="/user/3">ユーザーID: 3</router-link></li>
        </ul>
        <router-view></router-view>
    </div>

    <script>
        const User = {
            template: `
                <div class="user">
                    <h2>ユーザーIDは{{ $route.params.userId }}です。</h2>
                    <router-link :to="'/user/' + $route.params.userId + '/profile'">ユーザーのプロフィールページを見る</router-link>
                    <router-link :to="'/user/' + $route.params.userId + '/posts'">ユーザーの投稿ページを見る</router-link>
                    <router-view></router-view>
                </div>
            `
        }

        const UserProfile = {
            template: `
                <div class="user-profile">
                    <h3>こちらはユーザー{{ $route.params.userId }}のプロフィールページです。</h3>
                </div>
            `
        }

        const UserPosts = {
            template: `
                <div class="user-posts">
                    <h3>こちらはユーザー{{ $route.params.userId }}の投稿ページです。</h3>
                </div>
            `
        }

        const router = new VueRouter({
            routes: [
                {
                    path: '/user/:userId',
                    name: 'user',
                    component: User,
                    children: [
                        {
                            path: 'profile',
                            component: UserProfile
                        },
                        {
                            path: 'posts',
                            component: UserPosts
                        }
                    ]
                }
            ]
        })

        new Vue({
            el: '#app',
            router: router,
        })
    </script>
</body>
</html>

f:id:kojirooooocks:20181203053327g:plain

終わりに

サーバーサイド側のプログラムしかやってない自分にとって、とても革新的で、Vue Routerすごいなー!と思いました。

自分で作るとめっちゃ楽しいです。

さぁ次は第5章です。

がんばります。