LoginSignup
16
13

More than 1 year has passed since last update.

【Vue2】 Vue Routerの機能の整理

Posted at

Vue Routerを使う

  • インストール
npm i vue-router
  • vue-routerの設定を行う(ルーティングとコンポーネントの紐づけ) ( /src/router.js )
import Vue from 'vue';
import Router from 'vue-router'
import Home from '/views/Home.vue' 
import About from '/views/About.vue'

Vue.use(Router) // プラグイン(どこでも使える機能)を適用するために記載

export default new Router({
    routes:[
        {
            path:'/',           // URL 
            component:'Home'    // 上記URLのときに表示するコンポーネント
        },
        {
            path: '/about',
            component:'About'   
        }
    ]
})
  • routerをVueのグロバルコンポーネントで適用する( /src/main.js )
import Vue from 'vue'
import App from './App.vue'
import router from './router'

Vue.config.productionTip = false

new Vue({
    router,
    render: h => h(App)
}).$mount("app")
  • 表示個所にrouter-viewを用意する (/src/App.vue)
<template>
    <div>
        <router-view></router-view>
    </div>
</template>

さまざまな機能

URLの#を消す(mode:history)

デフォルトはmode:hashで、#がついている。mode: history とすることで、URLの#を消すことができる。

( /src/router.js 一部抜粋)

export default new Router({
    mode: 'history',
    routes:[ ... ]
})

URLを切り替える (router-link to="/")

<router-link to="リンク先">とすることで、指定したリンク先に遷移するリンクができる (/src/App.vue)

<template>
    <div>
        <router-link to="/"> HOME </router-link>
        <router-link to="/about"> ABOUT </router-link>
        <router-view></router-view>
    </div>
</template>

to属性はv-bindでバインディングできる。

URLに応じてクラスを変える (active-class)

active-class="クラス名"をすることでリンクを含むURLの時のみクラスが適用される。exactをつけることで完全一致するURLの時のみ適用されるクラスを設定できる。 (/src/App.vue)

<template>
    <div>
        <router-link to="/" active-class="active" exact> HOME </router-link>
        <router-link to="/about" active-class="active"> ABOUT </router-link>
        <router-view></router-view>
    </div>
</template>

<style scoped>
.active{
    font-size: 30px;
}
</style>

URLをJavaScriptから変更する($router.push)

this.$router.push({path: '遷移先URL'})とすることで、JavaScriptから遷移させることができる(/src/App.vue)

<template>
    <div>
        <button @click="toAbout">to About</button>
        <router-view></router-view>
    </div>
</template>

<script>
export default {
    methods: {
        toAbout() {
            this.$router.push({path: 'about'})
        }
    }
}
</script>

動的なURL(path: /xxx/:yyy, $route.params)

path '/xxx/:yyy'のように、コロンを使ってパラメータ(yyy)を指定することで、動的なURLができる

(/src/router.js 一部抜粋)

export default new Router({
    routes:[
        {
            path:'/',            
            component:'Home'    
        },
        {
            path: '/about/:id', // パラメータidを指定
            component:'About'   
        }
    ]
})

$route.params.idで動的なURLのパラメータにアクセスできる (/src/views/About.vue)

<template>
    <div>
        <!--  -->
        <p>No. {{$route.params.id}}</p>
    </div>
</template>

※ 動的なURLはライフサイクルフックが呼ばれないので、URLの変更で何か処理をさせたい場合は、watchで$routeを監視する。

動的なURLのパラメータをpropsからアクセス (props: true)

props: trueにすることで、動的パラメータをpropsでアクセスできる

(/src/router.js 一部抜粋)

export default new Router({
    routes:[
        {
            path:'/',            
            component:'Home'    
        },
        {
            path: '/about/:id', 
            component:'About',
            props: true         // propsを追加
        }
    ]
})

$route.params.idで動的なURLのパラメータにアクセスできる (/src/views/About.vue)

<template>
    <div>
        <p>ID: {{id}}</p>
    </div>
</template>

<script>
export default{
    props: ['id']
}
</script>

※ 動的なURLはライフサイクルフックが呼ばれないので、URLの変更で何か処理をさせたい場合は、watchで$routeを監視する。

router-view のなかにrouter-view (children)

childrenを追加することでネストされたrouter-viewを実現できる (/src/router.js)

import Vue from 'vue';
import Router from 'vue-router'
import Home from '/views/Home.vue' 
import About from '/views/About.vue'
import AboutChild from '/views/AboutChild.vue'

Vue.use(Router)

export default new Router({
    routes:[
        {
            path:'/',            
            component:'Home'    
        },
        {
            path: '/about', 
            component:'About',
            children:: [ // childrenオプションでpath, componentを設定する
                {path: "child", component: AboutChild} // …/about/childでアクセス可
            ]
        }
    ]
})

名前付きのルートを使う (name)

nameを使ってルートに名前を設定する (/src/router.js 一部抜粋)

export default new Router({
    routes:[
        {
            path: '/about:id', 
            component:'About',
            children:: [{
                path: "child",
                component: AboutChild,
                name: 'name-child'  // ルートの名前を設定
            }]
        }
    ]
})

nameで指定したルートの名前を渡す。パラメータはparamsでオブジェクトで指定する (/src/views/App.js)

<template>
    <div>
        <router-link :to= "{name:'name-child', params:{id:1}}"> ABOUT </router-link>
        <router-view></router-view>
    </div>
</template>

クエリにアクセス (query)

(/src/router.js 一部抜粋)

export default new Router({
    routes:[
        {
            path: '/about', 
            component:'About',
            name: 'about' // 名前付きルートを設定
        }
    ]
})

クリックすると/about?id=1というURLになる (/src/App.vue)

<template>
    <div>
        <!-- クリックすると /about?id=1&page=2というURLになる-->
        <router-link :to= "{name:'about', query:{id:1, page:2}}"> ABOUT </router-link>
        <!-- こちらでも可能 -->
        <router-link to="/about?id=1&page=2"></router-link>
        <router-view></router-view>
    </div>
</template>

クエリはthis.$route.query.idで取得できる。

リダイレクト機能 (redirect)

redirectを使うことで、リダイレクトを実装できる (/src/router.js 一部抜粋)

export default new Router({
    routes:[
        {
            path: '/about', 
            component:'About'
        },
        {
            path:'*',       // アスタリスクを指定することで任意のURLという意味になる
            redirect:'/'    // 遷移先のURLを指定
        }
    ]
})

router-viewにトランジション (transition)

router-viewにもトランジションを適用させることができる (/src/App.vue)

<template>
    <div>
        <transitin name="fade" mode="out-in">
            <router-view></router-view>
        </transitin>
    </div>
</template>

<style scoped>
.fade-enter,
.fade-leave-to {
    opacity: 0;
}
.fade-enter-active,
.fade-leave-active{
    transition: opacity .5s    
}
</style>

# idを指定する (hash)

クリックすると/about#nextというURLになる (/src/App.vue)

<template>
    <div>
        <!-- クリックすると /about#nextというURLになる-->
        <router-link :to= "{name:'about', hash: 'next'}"> ABOUT </router-link>
        <!-- こちらでも可能 -->
        <router-link to="/about#next"></router-link>
        <router-view></router-view>
    </div>
</template>

指定IDにスクロールさせる (scrollBehavior)

トランジションがない場合のみ使用できる。これは、transitionがあると、#nextが発生する前にscrollBehaviorが起動するためである (/src/router.js 一部抜粋)

export default new Router({
    routes:[
        {
            path:'/',            
            component:'Home'    
        }
    ],
    scrollBehavior(to, from, savedPosition) {
        // 前回の位置に戻る
        if(savedPosition) {
            return savedPosition
        }
        // URLにhashが含んでいたらハッシュの位置まで移動
        if(to.hash) {
            return {
                selector: to.hash
            }
        }
        // ページの先頭に移動
        return {x: 0, y: 0}
    }
})

すべてのページの遷移時に実行する (beforeEach)

/src/main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'

Vue.config.productionTip = false

// to:$route(次の遷移先の状態) from:$route(前の状態) next:次の遷移先に進む関数
router.beforeEach((to, from, next) => {
    console.log('before each!')
    // 引数も取れる
    // next(false):次に遷移させない
    // next('/'):'/'に遷移
    next()
})

new Vue({
    router,
    render: h => h(App)
}).$mount("#app")

特定のページの遷移時に実行する (beforeEnter)

boforeEnterを使う (/src/router.js 一部抜粋)

export default new Router({
    routes:[
        {
            path: '/about', 
            component:'About',
            beforeEnter(to, from, next) {
                console.log('before enter!')
                // 引数も取れる
                // next(false):次に遷移させない
                // next('/'):'/'に遷移
                next()
            }
        },

    ]
})

ナビゲーションガードをコンポーネントに指定

Vueコンポーネントに記載する

<script>
export default {
    beforeRouteEnter(to, from, next) {
        // コンポーネントを描画するルートが確立する前
        next()
    },
    beforeRouteUpdate(to, from, next) {
        // コンポーネントを描画するルートが変更されたとき
        next()
    },
    boforeRouteLeave(to, from, next) {
        //  コンポーネント終了後(ナビゲーションから離れていく時)
        const isLeave = window.confirm("このページを離れますか?")
        if(isLeave) {
            next()
        }else {
            next(false)        
        }
    }
}
</script>

遅延ローディング (const xx = () => import("./xxx.vue"))

router.jsのimport分の記載方法を変えることで遅延ローディング(後からjavascriptを取得する)が可能

(router.jsの一部を抜粋)

// ● 今までの書き方
// import Home from './views/Home.vue' 

// ● 遅延ローディングの場合
const Home = () => import(/* webpackChunkName: "Home" */ "./views/Home.vue")

参考

16
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
13