Vue.jsのvue-routerを使いこなす!実例で解説|SPAのぺージ遷移を簡単に実装する方法(WebpackやRailsで使う方法)

vue-js-prograshi(プロぐらし)-kv Vue.js
記事内に広告が含まれていることがあります。

Vue.jsでvue-routerというモジュールを使うと、とても簡単にSPA(シングルページアプリケーション)を作成することができます。

ここでは、vue-routerのインストール方法から実際の使い方まで実例で解説しています。

合わせて読みたい

この記事の内容はvue-routerを実際のプロジェクトで使用する場合のディレクトリ構造など少し踏み込んだ解説になっています。

vue-routerって何?SPAって何?vue-routerをサクッと試してみたいという方は下記をご参考ください。

【Vue.js】Vue RouterやSPAとは何か?メリット・デメリットと使い方を実例でわかりやすく解説|CDNを使ってサクッとSPAを試す方法


vue-routerのインストール

vue-routerを使うには、vue-routerをアプリケーションで読み込む必要があります。大きく3通りの方法があります。

  1. scriptタグでCDNを読み込む
  2. Vue CLIでvue-routerを選択する
  3. vue-routerモジュールをインストールする

CDNを読み込む

vue-routerをCDNで読み込む場合は、バージョンを指定する方法と最新のバージョンを使う方法の2通りがあります。

(以下の例ではあわせてVueのCDNも読み込んでいます。)

▼最新バージョンを使う場合

<script src="https://unpkg.com/vue@next"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>

▼バージョンを指定する場合

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router@3.0.7/dist/vue-router.js"></script>

上記scriptタグをbodyタグ終端の上に設置します。

(参考)


Vue CLIでvue-routerを選択する

Vue CLIとは、コマンドライン上でVue.jsを使う環境を構築できる機能です。@vue/cliをインストールして行います。

Vue CLIのインストールとプロジェクト新規作成方法についてはVue CLIの公式ページをご参考ください。

新規作成時にアプリケーションに導入する機能を選択する箇所があります。ここでRouterを選択すると、vue-router導入済みのアプリケーションが構築されます。

Vue CLI v3.7.0
? Please pick a preset: Manually select features
? Check the features needed for your project: (Press <space> to select, <a> to toggle al
l, <i> to invert selection)
❯◉ Babel
 ◯ TypeScript
 ◯ Progressive Web App (PWA) Support
 ◯ Router
 ◯ Vuex
 ◯ CSS Pre-processors
 ◉ Linter / Formatter
 ◯ Unit Testing
 ◯ E2E Testing

vue-routerなしでアプリケーションを構築した場合も、後から追加できます。

vue add vue-router


vue-routerモジュールのインストール

vue-routerのモジュールは、Node.jsのモジュール管理パッケージのnpmまたはyarnでインストールできます。

モジュールをインストールした場合は、JavaScriptファイルでそのモジュールをimportする必要があります。

vue-routerのインストール

▼yarn

yarn add vue-router

▼npm

npm install vue-router

モジュールの読み込み

モジュールをインストールした後は、読み込みむためには4つステップでJavaScritpファイルに処理追記する必要があります。

  1. importでそのモジュールを読み込む
  2. Vue.use()でVueのプラグインとして呼び出す。(Vueの追加機能となるモジュールをプラグインと呼びます)
  3. VueRouterのインスタンスを生成する。
  4. new VueでVueのインスタンスを生成するときに、VueRouterのインスタンスを追加する。


import Vue from 'vue'
import VueRouter from 'vue-router'   //1.インポート

Vue.use(VueRouter)   //2.Vueのプラグインとして呼び出し
const router = new VueRouter();    //3.インスタンス生成

document.addEventListener('DOMContentLoaded', () => {
  const app = new Vue({
    router,     //4. インスタンスを追加
    render: h => h(App)
  }).$mount('#app')

以上で準備が完了です。


実例

yarnを使ってインストールした場合は以下のようになります。

# yarn add vue-router
yarn add v1.22.5
[1/4] Resolving packages...
[2/4] Fetching packages...
info fsevents@2.3.2: The platform "linux" is incompatible with this module.
・
・
・
└─ vue-router@3.5.2
Done in 252.66s.


vue-routerとvuetifyの2つのプラグインをインストールする場合。

import Vue from 'vue'
import VueRouter from 'vue-router' //追加
import App from '../app.vue'
import Vuetify from 'vuetify'
import 'vuetify/dist/vuetify.min.css'

Vue.use(VueRouter) //追加
const router = new VueRouter() 

Vue.use(Vuetify) 
const vuetify = new Vuetify() 

document.addEventListener('DOMContentLoaded', () => {
  const app = new Vue({
    router, //追加
    vuetify, 
    render: h => h(App)
  }).$mount()
  document.body.appendChild(app.$el)
})


(参考)


vue-routerの設定ファイルを分割する方法

上記のように、vue-routerをVueインスタンスを生成するファイルで読み込むと、ルーティングを追加していったときに、vue-routerの処理が多くなりファイルが読みにくくなります。

そこで、vue-routerのファイルは別途用意し、Vueインスタンスを生成するファイルにインポートする方がスッキリします。

vue-routerの処理を別ファイルに書き出す方法を2つ紹介します。

  1. JavaScriptファイルに書き出す(例:router.js)
  2. Vue.jsファイルに書き出す(例:app.vue)


JavaScriptファイルに書き出す方法(router.js)

Vueインスタンスを生成するファイルをmain.js、vue-routerの設定を記述するファイルをrouter.jsとし並列に配置します。

|- main.js
|- router.js

router.js

vue-routerの処理を記述するrouter.jsは以下のようになります。

import Vue from 'vue'
import VueRouter from 'vue-router'
//使用するコンポーネントを追加でimportする

Vue.use(VueRouter)

export default new VueRouter({
  //vue-routerの設定(モードやコンポーネントの設定)
})

Vue.useを使うので、vueモジュールのimportも必要になります。

main.js

Vueインスタンスを生成する、main.jsは以下のようになります。

import Vue from 'vue'
import router from './router' //追加

new Vue({
  router, //追加
  render: h => h(App)
}).$mount('#app')

これで、ファイルの中身がシンプルになります。

import router from ‘./router’

同じ階層にあるrouter.jsをrouterという名前で読み込んでいます。拡張子(.jsや.vue)は省略できます。

▼import fromの基本構文

import エクスポート名 from モジュール

(参考)MDN JacaScript import


export default

exportとは、JavaScriptをモジュール化して外から呼び出せるようにする記述です。このファイルをimportしたときに、exportの中で定義されている内容を呼び出すことができます。

exportには名前付きエクスポートと、デフォルト(default)エクスポートがあります。

通常のexportは変数や関数毎に名前をつけて呼び出します(名前付きエクスポート)。これに対して、export defaultとすると、その処理の中身全体を1つのモジュールとして出力することができます。

(参考)MDN JavaScript export


Vue.jsファイルに書き出す方法(例:app.vue)

JavaScirptファイルに書き出す以外にも、共通レイアウトとなるVueファイルのscriptタグ部分に記述する方法もあります。

こちらの方が、ルーティングファイルを呼び出すrouter-viewタグを記述したtemplateタグと同じ場所にルーティングの設定を記述できるのでわかりやすいです。

Vueインスタンスを生成するファイルをmain.jsの中で呼び出しているapp.vueファイルをVueの共通レイアウトとして、vue-routerの設定を記述します。

ディレクトリ構造の例は以下のようになります。(webpack使用時)

|- javascript
|     |
|     |- packs
|     |    |- main.js
|     |
|     |- app.vue

app.vue

共通テンプレートとなるVueファイルの中身は次のようになります。

<template>
  <div>
    <router-view></router-view>
  </div>
</template>

<script>
import Vue from 'vue'
import VueRouter from 'vue-router'

//使用するコンポーネントを追加でimportする

Vue.use(VueRouter)

const router = new VueRouter({
  //vue-routerの設定(モードやコンポーネントの設定)
})

export default {
  router
}
</script>

<style scoped>
</style>

router-viewタグの部分に指定したルーティングに対応するテンプレートが読み込まれます。

共通となるレイアウトはtemplate直下のdivタグの中に記述します。

tips

Vue単一テンプレート直下にはタグを1つしか記述できません。

通常divタグが使われることが多いですが、sectionタグなど他のタグでも問題ありません。


main.js

Vueインスタンスを生成する、main.jsは以下のようになります。

import Vue from 'vue'
import App from '../app.vue' //追加

document.addEventListener('DOMContentLoaded', () => {
  const app = new Vue({
    render: h => h(App)
  }).$mount()
  document.body.appendChild(app.$el)
})


テンプレートの作成と読み込み

Vue.jsのテンプレートを作成し、vue-routerを使ってページ遷移してそのテンプレートを呼び出す手順について解説します。

テンプレートの準備

トップページ(https://example.com/#/)にアクセスしたときに表示するTop.vueを作成します。

ここでは、componentsというディレクトリを作成しその中にテンプレートファイルを配置します。

|- javascript
|     |
|     |- packs
|     |    |- main.js
|     |
|     |- app.vue
|     |
|     |- components
|          |- Top.vue

Top.vue

h1タグで「Topページ」と表示するテンプレートです。

<template>
  <div>
      <h1>Topページ</h1>
  </div>
</template>

<script>
export default {

}
</script>

<style lang="scss" scoped>
h1{
    color: blue;
    font-weight: bold;
}
</style>

styleタグにscopedを記述すると、記述したスタイルはこのVueファイルのみ限定して適用できます。


vue-routerでテンプレートを読み込む

vue-routerの設定で、作成したテンプレートを読み込み、トップページにアクセスしたときにTop.vueを読み込むルーティングを作成します。

<template>
  <div>
    <header>共通ヘッダー</header>
    
    <router-view></router-view>
    
    <footer>共通フッター</footer>
  </div>
</template>

<script>
import Vue from 'vue'
import VueRouter from 'vue-router'

import Top from './components/Top'

Vue.use(VueRouter)

const router = new VueRouter({
  routes: [
    { path: '/',
      component: Top  },
  ]
})

export default {
  router
}
</script>

<style scoped>
</style>

参考に共通レイアウトのパーツとして、headerタグとfooterタグを設置しています。


ブラウザの表示

指定したルートにアクセスして、作成したテンプレートの内容が表示されるかを確認します。

URLはhttp://localhost:3000/#/のように、/#/がつきます。

URLの#(ハッシュ)を取り除く方法

vue-routerを使用するとURLに(ここでは、シャープではなく、ハッシュと読みます)が入ります。

この#は簡単に取り除くことができます。

historyモードの設定

#は簡単に取り除くには、vue-routerの設定にmode: 'history'を追記します。

実例

<template>
  <div>
    <header>共通ヘッダー</header>
    
    <router-view></router-view>
    
    <footer>共通フッター</footer>
  </div>
</template>

<script>
import Vue from 'vue'
import VueRouter from 'vue-router'

import Top from './components/Top'

Vue.use(VueRouter)

const router = new VueRouter({
  mode: 'history',  //追記
  routes: [
    { path: '/',
      component: Top  },
  ]
})

export default {
  router
}
</script>

<style scoped>
</style>

これで、#なしでページを読みこむことができます。

historyモードの注意点

historyモードは個別にページを用意したわけではなく、SPAです。単に#(ハッシュ)が省略されただけの状態です。

ここで、問題は、ユーザーがブラウザで直接、そのルートを叩くと、サーバー側でそのルーティングを設定していない場合はエラーが発生します。

historyモードにした場合は、追加したルートに対応するルートを、サーバーのルーティングにも追加する必要があります。

そのルーティングでアクセスするのは、ビューインスタンスを生成するファイルです。

Railsの例

例えば以下のように、/topにアクセスしたらTop.vueを開くルーティングを追加したとします。

<template>
  <div>
    <header>共通ヘッダー</header>
    
    <router-view></router-view>
    
    <footer>共通フッター</footer>
  </div>
</template>

<script>
import Vue from 'vue'
import VueRouter from 'vue-router'

import Top from './components/Top'

Vue.use(VueRouter)

const router = new VueRouter({
  mode: 'history',  //historyモード
  routes: [
    { path: '/top',  //ルーティング
      component: Top  },
  ]
})

export default {
  router
}
</script>

<style scoped>
</style>

この状態で、ブラウザで直接、/topにアクセスするとルーティングエラーが発生します。


正しく動作させるためには、/topにアクセスしたときに、Vueインスタンスを作成するビューファイルにアクセスするコントローラとアクションをルーティングで指定する必要があります。

例えば、homeコントローラのindexアクションで対象のVueファイルにアクセスする場合は、以下のようになります。

▼routes.rb

Rails.application.routes.draw do

  ActiveAdmin.routes(self)
  root 'home#index'
  get '/top', to: 'home#index'  #追記
end

この状態であれば、ブラウザで/topにアクセスすると、vue-routerで設定した/topのルーティングに対応するページが表示されます。

対外的なアプリケーションでなければ、特にhistoryモードにする必要もないでしょう。

(参考)Vue Router HTML5 History モード


存在しないルートにアクセスしたときに404ページを表示する方法

デフォルトの状態では、#(ハッシュ)以下で設定していないルートを指定した場合に、共通テンプレートが表示されます。

例: http://localhost:3000/#/page-not-exist

vue-routerで該当するルートが存在しない場合に404(エラー)ページを表示する方法は次の2つの手順で実現できます。

  1. 404(エラー)ページを用意する
  2. ルーティングを追加する

404(エラー)ページを用意する

components配下に404.vueというページを用意します。(ディレクトリやファイル名はよしなに。)

<template>
  <div id="error">
      <h1>Page Not Found</h1>
      <a href="/">Return To Top</a>
  </div>
</template>

<script>
export default {

}
</script>

<style lang="scss" scoped>
#error{
    color: red
}
</style>


ルーティングを追加する

vue-routerのルーティングは上から順に適用されていきます。設定していないすべてのページを指定するためにはアスタリスク「*」を使います。

ルーティングの一番最後に、{ path: '*',    component: エラーテンプレート名  } を追記します。

<template>
  <div>
    <header>共通ヘッダー</header>
    
    <router-view></router-view>
    
    <footer>共通フッター</footer>
  </div>
</template>

<script>
import Vue from 'vue'
import VueRouter from 'vue-router'

import Top from './components/Top'
import Error from './components/404' //404.vueの読み込み

Vue.use(VueRouter)

const router = new VueRouter({
  routes: [
    { path: '/',
      component: Top  },
    { path: '*',
    component: Error  }  //エラーページへのルーティング
  ]
})

export default {
  router
}
</script>

<style scoped>
</style>

ブラウザで確認

この状態で、ブラウザに存在しないURLを入力すると、404.vueが表示されます。

tips

ワイルドカードの「*」は前方一致でも使えます。

{path: '/user-*', 処理} とすれば/user-から始まるすべてのURIが対象となります。


パラメータを使った動的なパス(URI)の指定

ルーティングにパラメータを使ったURIを指定することもできます。(Vue.jsの公式ページでは動的ルートマッチングと呼んでいます)

パラメータの指定方法

パラメータを指定するには:パラメータ名 とします。

例えば、/user/:name というルーティングを作成した場合、user/testでアクセスがあると、このルーティングで指定したテンプレートが表示されます。

そして、$route.paramsという変数の中に、パラメータ名: 該当するURIとして、入力されたパラメータの情報が渡されます。(user/testなら、 $route.params ={ "name": "test" }となります)

実例

/users/:name/posts/:post_idというURIにアクセスしたときに、ユーザーと指定したPost ID毎にページの内容を出しわける例です。

components配下にUserPostShow.vueというテンプレートを用意します。

テンプレートの用意(UserPostShow.vue)

<template>
  <div id="user-post-wrapper">
    <p>名前:{{ $route.params.name }}</p>
    <p>投稿ID:{{ $route.params.post_id }}</p>
    <p>$route.paramsの中身: {{$route.params}}</p>
  </div>
</template>

<script>
export default {

}
</script>

<style lang="scss" scoped>
#user-post-wrapper{
    color: blue;
    margin: 40px 10px;
    max-width: 600px;
    border: solid 1px gray;
}
</style>


ルーティングの設定

importでテンプレートを読み込んだあとに、以下のルーティングを追加します。

    { path: '/users/:name/posts/:post_id', component: UserPostShow  },

▼app.vueの全体像

<template>
  <div>
    <header>共通ヘッダー</header>
    
    <router-view></router-view>
    
    <footer>共通フッター</footer>
  </div>
</template>

<script>
import Vue from 'vue'
import VueRouter from 'vue-router'

import Top from './components/Top'
import Error from './components/404'
import UserPostShow from './components/UserPostShow'

Vue.use(VueRouter)

const router = new VueRouter({
  routes: [
    { path: '/',
      component: Top  },
    { path: '/users/:name/posts/:post_id',
      component: UserPostShow  },
    { path: '*',
    component: Error  }
  ]
})

export default {
  router
}
</script>

<style scoped>
</style>


ブラウザの表示

/users/test/posts/123にアクセスして、ユーザー名とPost IDをブラウザ上に表示させます。

例:http://localhost:3000/#/users/test/posts/123

ページの中身を動的に変更することができました。


ネストしたルーティング

vue-routerではルーティングをネストさせることもできます。

ルーティングのネストを使えば、呼び出したテンプレートの中で、URIに合わせて更にテンプレートを切り替えることができます。

例えば、個別のユーザーページ(users/:id)があり、ルーティングによって、その人のプロフィール(users/:id/profile)を表示したり、投稿した記事一覧(users/:id/posts)を表示するといった切り替えを行う場合に使います。

ネストしたルーティングの設定方法

ルーティングをネストするにはchildrenオプションを使います。

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

上記の設定の場合、/user/:idと、/user/:id/profileの2つのルーティングが設定されたことになります。

/user/:id/profileにアクセスがあった場合、Userテンプレートの中のrouter-vueタグの中に、UserProfileテンプレートが読み込まれます。


実例

個別のユーザーページ(users/:id)があり、ルーティングによって、その人のプロフィール(users/:id/profile)を表示したり、投稿した記事一覧(users/:id/posts)を表示するといった切り替える事例です。

URIテンプレート
users/:id User
users/:id/profile UserProfile
users/:id/posts UserPosts

UserProfileもUserPostもUseに関連するテンプレートなので、componentsの中にUserディレクトリを作成して、その中に各ファイルを置くようにします。

Userテンプレートの作成

components配下にUser.vueを作成します。

<template>
  <div id="user-wrapper">
    <p>ユーザーID:{{ $route.params.id }}</p>
    <router-view></router-view>
  </div>
</template>

<script>
export default {

}
</script>

<style lang="scss" scoprd>
#user-wrapper{
    color: blue;
    margin: 40px 10px;
    max-width: 600px;
    border: solid 1px gray;
}
</style>

UserProfileテンプレートの作成

components配下にUserProfile.vueを作成します。

<template>
  <div id="user-profile-wrapper">
    <h2>ユーザープロフィール</h2>
    <ul>
        <li>名前:</li>
        <li>年齢:</li>
        <li>性別:</li>
        <li>職業:</li>
    </ul>
  </div>
</template>

<script>
export default {

}
</script>

<style lang="scss" scoped>
#user-profile-wrapper{
    color: orange;
    margin: 20px 10px;
    padding-left: 30px;
    max-width: 400px;
    border: solid 1px gray;
}
</style>

通常は指定したid番号に該当するUser情報を他のページ(or DB)から取得して個別のデータを表示します。

あわせて読みたい

Vue.jsで他のページからデータを取得する場合にaxiosを使うと便利です。

axiosの使い方については下記をご参考ください。

axiosとは何か?Vue.jsでAPIのデータを取得する方法


UserPostsテンプレートの作成

components配下にUserPosts.vueを作成します。

<template>
  <div id="user-posts-wrapper">
    <h2>投稿一覧</h2>
    <ul>
        <li>投稿1:</li>
        <li>投稿2:</li>
        <li>投稿3:</li>
        <li>投稿4:</li>
    </ul>
  </div>
</template>

<script>
export default {

}
</script>

<style lang="scss" scoped>
#user-posts-wrapper{
    color: green;
    margin: 20px 10px;
    padding-left: 30px;
    max-width: 400px;
    border: solid 1px gray;
}
</style>


ルーティングの設定

childrenオプションを使ってルーティングを追加します。(テンプレートのimportをお忘れなく)

    {
      path: '/user/:id',
      component: User,
      children: [
        {
          path: 'profile',
          component: UserProfile
        },
        {
          path: 'posts',
          component: UserPosts
        }
      ]
    },

▼app.vueの全体像

<template>
  <div>
    <header>共通ヘッダー</header>
    
    <router-view></router-view>
    
    <footer>共通フッター</footer>
  </div>
</template>

<script>
import Vue from 'vue'
import VueRouter from 'vue-router'

import Top from './components/Top'
import Error from './components/404'

//テンプレートのimport
import User from './components/User/User'
import UserProfile from './components/User/UserProfile'
import UserPosts from './components/User/UserPosts'

Vue.use(VueRouter)

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

export default {
  router
}
</script>

<style scoped>
</style>

以上で準備は完了です。

ブラウザの表示

実際にブラウザでページを表示して、内容が切り替わるか確認します。

▼Userテンプレート

http://localhost:3000/#/user/123

▼UserProfileテンプレート

▼UserPostsテンプレート

ネストしたURIに合わせてページの内容を切り替えることができました。

(参考)Vue Router ネストされたルート


Vueテンプレートへのリンク設置方法

Vueテンプレート内で、設定したルーティングへのリンクを設置するには、router-linkタグを使います。

リンク先の指定には3つの方法があります。

  1. URIで指定する
  2. ルート名で指定する(別途設定が必要)
  3. プログラム的に遷移する

URI(パス)で指定する

最も基本的な書き方は、router-linkタグを使って、to属性でURIを指定することです。

<router-link to="URI">アンカーテキスト</router-link>

toで指定できるのは、通常の文字列以外にも、変数、文字列と変数の組み合わせがあります。

内容方法実例
文字列のみダブルクオテーションで囲む<router-link to=”/users/123″>
変数のみv-bindにする<router-link :to=”userId”>
変数と文字列・全体をダブルクオテーションで囲む
・文字列をシングルクオテーションで囲み、+でつなぐ
<router-link :to=”‘user/’+ id”>
変数と文字列 ・全体をダブルクオテーションで囲む
・変数を${}で囲む
<router-link :to=”`user/${id}`”>
オブジェクトpathプロパティでURIを渡す <router-link :to=”{ path: ‘user/123’}”>

以下でそれぞれの例を紹介します。

例1:通常のパス

ダブルクオテーションで文字列を囲みます。

<router-link to="/users/123">User ID 123</router-link>


例2:パスに変数を渡す(変数のみ)

パスに変数を渡したい場合はv-bindで渡します。

<router-link :to="userId">User ID 123</router-link>

<script>
export default {
    data(){
        return{
            userId: "user/123",
        }
    }

}
</script>
tips

:属性名v-bind:属性名の省略形です。

v-bindにすれば、値にvueの変数やメソッドを指定できます。


例3:パスに変数と文字列を渡す

パスで文字列と変数を結合して指定したい場合は、シングルクオテーションの中で、

  • 文字列はダブルクオテーションで囲む
  • 文字列と変数をつなぐときは + を使います。
<router-link :to='"user/"+ id'>リンク</router-link>

<script>
export default {
    data(){
        return{
            id: 123
        }
    }

}
</script>
tips

外側をダブルクオテーションで囲み、文字列をシングルクオテーションで囲む方法も使えます。

ポイントは同じ記号を使っていないことです。


例4:パスに変数と文字列を渡す(テンプレートリテラル)

パスで文字列と変数を結合して指定したい場合に、で結合するのではなく、変数を${変数}として、文字列の中に埋め込む方法もあります。

注意点

テンプレートリテラルを使う場合も、v-bindを使い、値をダブルクオテーションで囲む必要があります。

その中で文字列と変数をバッククオート(shift + @)で囲みます。

<router-link :to="`user/${id}`">リンク</router-link>

<script>
export default {
    data(){
        return{
            id: 123
        }
    }

}
</script>

(参考)MDN JavaScriptテンプレートリテラル (テンプレート文字列)


例5:オブジェクトでパスを指定する

v-bindしたto属性に、オブジェクトでpathを指定することもできます。

 <router-link :to="{ path: 'user/123'}">リンク</router-link>



ルート名で指定する

ルーティングにルート名を設定し、to属性でルート名を指定する方法もあります。

ルート名の指定方法

ルート名を指定するには、nameオプションを使います。

/user/:userIdというルートにuserという名前を付ける場合は次のようになります。

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


ルート名でリンクを設置する方法(パラメータなし)

名前を使ってリンクを設置するときは、v-bindにしてプロパティでキー名にnameを, 値にテンプレート名を指定します。

<router-link :to="{name: 'テンプレート名'}">アンカーテキスト</router-link>


ルート名でリンクを設置する方法(パラメータあり)

/user/:idのように、テンプレートのパスにパラメータが必要な場合は、オブジェクトの中に、paramsプロパティを追加し、その中でパラメータ名と値のセットを渡します。

<router-link :to="{name: 'テンプレート名', params: { パラメータ名1: 値1, パラメータ名2: 値2, パラメータ名3: 値3,,, }}">アンカーテキスト</router-link>
tips

値に文字列を指定する場合は、変数と区別するために、シングルクオテーションやダブルクオテーションで囲みます。

▼例

/user/:idのパスに対応するテンプレートに、Userという名前がついている場合は次のようになります。

<router-link :to="{ name: 'User', params: { id: 123 }}">アンカーテキスト</router-link>


ルート名でリンクを設置する方法(クエリの指定)

/user/:id?age=23&gender=male のようにパスの後ろに?(GETメソッド)を使ったURIを作成したいときは、toに渡すオブジェクトの中に、queryというプロパティを追加します。

<router-link :to="{name: 'テンプレート名', query: {キー名1:値1, キー名2:値2,,,} }">アンカーテキスト</router-link>

paramsと組み合わせることもできます。

▼例

<router-link :to="{ name: 'yama', query: { keyword:'peak', height:3000, place: 'shizuoka' } } ">Mountain</router-link>

上記のリンク先のURLは、次のようになります。

http://localhost:3000/#/mountain?keyword=peak&height=3000&place=shizuoka




プログラム的に遷移する($router.push)

router-linkタグを使って他のテンプレートへのリンクを設置する以外にも、router.pushというメソッドを使って、プログラム的な書き方でリンクすることもできます。(VueRouterの公式ページで「プログラム的」と呼んでいます)

注意点

現在のルートの情報が入っている$routeとは異なります。($routeをルートオブジェクトと呼びます)

基本的な使い方は次のようになります。

router.push('パス')

router-linkタグをクリックした結果がrouter.pushなので、引数にはrouter-linkのto属性の指定とまったく同じものが使えます。

// 文字列でパスを指定
router.push('パス')

// オブジェクトで指定
router.push({ path: 'パス' })

// 名前付きルート(パラメータあり)
router.push({ name: 'テンプレート名', params: { パラメータ名: 値 } })

// クエリの指定
router.push({ path: 'パス', query: { キー名: 値 } })
tips

Vueテンプレートの中で、実際に使う場合は$route.pushとします。

export defaultの中で使う場合は、this.$route.pushとなります。

$routeはVueRouterのインスタンスです。


(参考)Vue Router プログラムによるナビゲーション

実例

クリックしたときに指定したパスに遷移するには、clickイベントとメソッドを組み合わせます。

例えば、次のように大本のapp.vueにUserテンプレートへのルーティングがあり、テンプレート名にnameが指定されている場合に、トップページ内でrouter.pushを使ってUserテンプレートへのリンクを設置する例です。

▼ルーティングの設定

const router = new VueRouter({
  routes: [
    { path: '/',
      component: Top  },
    {
      path: '/user/:id',
      component: User,
      name: 'user',
     }
  ]
})


▼Topページに設置するリンク

<p @click="linkToUser(123)">User</p>
export default {
    methods:{
        linkToUser(userId){
            this.$router.push( {name: 'user', params: { id: userId }} )
        }
    }
}


これでブラウザ上に表示されている「User」という文字をクリックすると、http://localhost:3000/#/user/123 にアクセスします。

tips

@clickのアットマークは、v-onの省略記法です。

@clickは、v-on:clickと同じです。

(参考)Vue.js v-on 省略記法


router-linkの様々なオプション

router-linkタグには、便利なオプション属性が用意されています。

例えば、通常であればrouter-linkタグはコンパイル後にaタグに変換されます。別のタグにしたい場合に、tag属性をつければ、指定したタグに変換することができます(リンクも機能します)

      <router-link :to="パス" tag="タグ">アンカーテキスト</router-link>

tag="li"とすればliタグとして、tag="p"とすればpタグとしてコンパイルされます。

このように、router-linkには様々なオプションが用意されているのでよかったら下記も参考にしてみてください。

(参考)Vue Router APIリファレンス <router-link>


リダイレクトの設定

VueRouterでは、ルーティングの設定時にredirectオプションをつけるだけで、リダイレクトの設定が簡単にできます。

パスで指定する場合

routes: [
  { 
    path: '元のパス',
    redirect: 'リダイレクト後のパス' 
  }
]


オブジェクトで指定する場合

テンプレート名で指定する場合など、オブジェクトで指定ができます。

routes: [
  { 
    path: '元のパス',
    redirect: { name: 'リダイレクト後のテンプレート名' }
  }
]
tips

サーバー側でルーティングの設定がない場合、SPAなので、URLが変わるのみでステータスコードは変化しません。(301, 302にはならず、200のままです)


templateタグ内で複数のrouter-viewを使う方法

1つのビューの中で、複数のVueテンプレートを呼び出すこともできます。

例えば、ヘッダー、メインコンテンツ、フッターをそれぞれVueテンプレートで呼び出すには、1つのtemlateタグの中に、router-viewタグを3つ設置し、テンプレートを出しわける必要があります。

複数のrouter-viewの使い方

router-viewで呼び出すテンプレートを指定するには2つのステップを踏む必要があります。

  1. ルーティングのcomponentsにテンプレートを登録する。
  2. router-viewの中でname属性を使って呼び出すテンプレートを指定する。

ルーティングのcomponentsでテンプレートを登録する方法

1つのtemplateタグの中で複数のVueテンプレートを呼び出す場合は、componentsオプションを使います。(※複数形になります)

      components: {
        default: テンプレート1,
        テンプレート名2: テンプレート2,
        テンプレート名3: テンプレート3,
    ・
    ・
    ・
      }

defaultというのが、router-viewにname属性をつけていないときに呼び出すテンプレートです。

それぞれのテンプレートをimportするのを忘れないようにしてください。


router-viewの中でname属性を使って呼び出すテンプレートを指定

あとは、router-viewタグのname属性の値にテンプレート名を指定すれば、対象のテンプレートが呼び出されます。

<router-view name="テンプレート名"></router-view>

※対象のテンプレートがない場合は何も表示されません。

classやidをつけたい場合は、属性として追加すればHTMLにコンパイルしたときに反映されます。

▼classやidの指定

<router-view name="テンプレート名" id="id名" class="class名"></router-view>
注意点

vue-routerを使って表示するテンプレートは、ページを遷移すると切り替わります。

このため、vue-routerでHeaderやFooterを指定する場合は、遷移後のページにも同じようパーツを表示したい場合は、それぞれを呼び出す記述が必要になります。


実例

ヘッダー、メインコンテンツ、フッターをそれぞれVueテンプレートで呼び出す例を紹介します。

ディレクトリ構造は以下のようにしています。components配下にlayoutsディレクトリを作成し、その中でHeader.vueとFooter.vueを配置しています。

|- javascript
|     |
|     |- packs
|     |    |- main.js
|     |
|     |- app.vue
|     |
|     |- components
|          |- Top.vue
|          |
|          |- layouts
|                |- Header.vue
|                |- Footer.vue
  • main.js:Vueインスタンスの生成
  • app.vue: vue-routerの設定
  • Top.vue: メインコンテンツ用のテンプレート
  • Header.vue: ヘッダー用のテンプレート
  • Footer.vue: フッター用のテンプレート

まずは、Top.vue, Header.vue, Footer.vueの3つのテンプレートを作成します。(目的はrouter-viewを使ったテンプレートの出し分けなのでシンプルです。適宜カスタマイズしてください。)

Header.vue テンプレートの作成

<template>
  <div>
      <hr>
      <h2>This is Header</h2>
      <hr>
  </div>
</template>

<script>
export default {

}
</script>

<style lang="scss" scoped>
div{
    margin: 30px 0;
}
</style>


Foooter .vue テンプレートの作成

<template>
  <div>
      <hr>
      <h2>This is Footer</h2>
      <hr>
  </div>
</template>

<script>
export default {

}
</script>

<style lang="scss" scoped>
div{
    margin: 30px 0;
}
</style>

Top.vueテンプレートの作成

<template>
  <div>
      <h1>Topページ</h1>
  </div>
</template>

<script>
export default {
}
</script>

<style lang="scss" scoped>
h1{
    color: blue;
    font-weight: bold;
}
</style>


vue-routerの設定

続いて、app.vueファイルの中に、vue-routerでそれぞれのテンプレートを使う設定(components)と、router-viewタグの記述を行います。

<template>
  <div>
    <router-view name="header" class="header" id="header-id"></router-view>
    <router-view></router-view>
    <router-view name="footer"></router-view>
  </div>
</template>

<script>
import Vue from 'vue'
import VueRouter from 'vue-router'

import Top from './components/Top'
import Header from './components/layouts/Header'
import Footer from './components/layouts/Footer'

Vue.use(VueRouter)

const router = new VueRouter({
  routes: [
    {
      path: '/',
      components: {
        default: Top,
        header: Header,
        footer: Footer
      }
    }
  ]
})

export default {
  router
}
</script>

<style scoped>
</style>

以上で設定は完了です。


ブラウザの表示

ブラウザで各テンプレートが正しく読み込まれるか確認します。

指定したルーティング / にアクセスします。

各テンプレートが正しく読み込まれました。

Header.vueテンプレートの読み込み時に指定した、idとclassも読み込まれています。

tips

上記のdata-v-6fb8108aというのは、Vueのアプリケーションに自動で割り振られる属性です。

data-v-*が2つあるのは、テンプレートの中にscope付きのstyleタグがあるためです。(scope付きのstyleタグを指定すると、個別のハッシュ値を割り振って識別をします)

scope付きのstyleタグを取り除けば、data-v-*は1つになります。


補足

上記のようにrouter-viewでヘッダーやフッターを指定すると、遷移先のページで同じように呼び出す設定がされていない場合は、ヘッダーやフッターが表示されなくなります。

実用的には、テンプレートとして呼び出します。

templateタグの中でテンプレートを呼び出す方法

templateタグの中でテンプレートを呼び出す手順は次のとおりです。

  1. scriptタグの中でテンプレートをimportする。
  2. export defaultの中に、componentsオプションを記述し、使用するテンプレートを指定する。
  3. templateタグの中で、テンプレート名のタグを記述する。

▼実例

<template>
  <div>
    <Header class="header" id="header-id" />
    <router-view></router-view>    
    <Footer />
  </div>
</template>

<script>
import Vue from 'vue'
import VueRouter from 'vue-router'

import Top from './components/Top'
import Header from './components/layouts/Header'
import Footer from './components/layouts/Footer'

Vue.use(VueRouter)

const router = new VueRouter({
  routes: [
    {
      path: '/',
      component: Top
    }
  ]
})

export default {
  router,
  components:{
    Header,
    Footer
  }
}
</script>

<style scoped>
</style>


便利な$routeの使い方

現在のURLやパラメータといった情報は$routeの中に入っています。($routeのことをルートオブジェクトと呼びます)

$routeに対して決まったプロパティ名を指定することでそれらのデータを呼び出すことができます。

ルート情報のプロパティ一覧

プロパティ名内容
path現在のURI
fullPath完全なURL(クエリ(?以下)も含む)
paramsパラメータ。Key:Valueで入っている
queryクエリ(URLの?以下)。 Key:Valueで入っている
name現在のルート名。ルーティングでnameが設定されている場合
redirectedFromリダイレクト元
hash現在のルートの#(ハッシュ)

(参考)Vue Router APIリファレンス <router-view> Props


実例

例えば、以下のように/users/:name/posts/:post_idに該当するルートがあるとします。

  routes: [   
    { 
      path: '/users/:name/posts/:post_id',
      component: UserPostShow,
      name: UserPostDetail
    },
  ]

この場合に、アクセス先のテンプレートのtemplateタグ内で各プロパティを呼び出す記述をしておきます。

<template>
  <div>
    <p>名前:{{ $route.params.name }}</p>
    <p>投稿ID:{{ $route.params.post_id }}</p>
    <p>params: {{$route.params}}</p>
    <p>path: {{$route.path}}</p>
    <p>fullPath: {{$route.fullPath}}</p>
    <p>query: {{$route.query}}</p>
    <p>name: {{$route.name}}</p>
    <p>redirectedFrom: {{$route.redirectedFrom}}</p>
    <p>hash: {{$route.hash}}</p>
  </div>
</template>

<script>
export default {

}
</script>

<style lang="scss" scoped>
}
</style>

この状態で、http://localhost:3000/#/users/test/posts/123?keyword=details&age=24にアクセスするとブラウザの表示は次のようになります。



正規表現でパスやパラメータを指定する方法

ルーティングの設定をする際に、正規表現を使ってパス(URI)の指定をすることができます。

正規表現を使う場所

routesの中のpathオプションの中で正規表現を指定するのみです。(正規表現を / / で囲う必要はありません)

  routes: [
    {
      path: '/users/:id(\\d+)',   //ここで正規表現を指定
      component: User,
      name: UserShow,
    },
  ・
  ・
  ・

例えば上記であれば、\dがすべての数字([0-9])で、が直前の文字の1回以上の繰り返しです。

\dの冒頭に\をつけることで、エスケープして\dが正規表現の特殊文字であることを示しています。

文字内容
\エスケープ
\d数値のみ。[0-9]と同じ
+直前の文字の1回以上の繰り返し

正規表現の例

  routes: [
    //パラメータがあってもなくてもいい
    { path: '/user/:id?' },

    //数値のみ
    { path: '/user/:id(\\d+)' },
    
    //前方一致
    { path: '/user/*' },

    //ディレクトリの一部をオプションにする
    { path: '/user/(company/)?posts' }
  ]

(参考)

タイトルとURLをコピーしました