LoginSignup
0
1

More than 1 year has passed since last update.

Vue Router を使って簡単に SPA 構築

Posted at

前提

端末: MacBook Pro
OS: macOS Catalina 10.15.7
Node.js: v12.18.3
Vue.js: v2.6.11
Vue-CLI: v4.5.13

Node.js, yarn, Vue 既にインストール済み
Vue-CLI を利用して、プロジェクトを作成済み

Vue Router とは

Vue.js を利用した SPA(シングルページアプリケーション)の構築において、ルーティング制御をするための公式プラグインのことを指す

SPA とは

複数ページではなく、単一のページで構成された web アプリケーションまたは web サイトのことを指す
初めに 1 つの html を読み込み、以後は Ajax で情報を動的にページを更新させる
新しい情報を読み込む際にページ遷移を行う必要がないため、ネイティブアプリのような動作をすることが可能

セットアップ

yarn でインストール
(Vue Cli でプロジェクト作成した場合だと、既にインストール済みの可能性あり)

$ yarn add vue-router

package.json に定義されているか確認

package.json
{
  "dependencies": {
    "core-js": "^3.6.5",
    "vue": "^2.6.11",
    "vue-router": "^3.5.1"
  },
}

簡単に SPA を作成する

router.js を /src 配下に作成する
(表示用のコンポーネントは適時作成)

router.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from './components/Home'
import Foo from './components/Foo'
import Bar from './components/Bar'

// モジュールとして使用する場合に必要
Vue.use(VueRouter)

// ルーターインスタンスを作成
export default new VueRouter({
  // デフォルトの挙動では url に # が含まれている(例: ~/#/foo)
  // history モードを指定することで url から hash を取り除くことが可能
  mode: 'history',

  // ルート定義において、各ルートは 1 つのコンポーネントとマッピングされる必要がある
  // 適時コンポーネント作成をお願いします => <template><div>HOME</div></template>
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home
    },

    {
      path: '/foo',
      name: 'foo',
      component: Foo
    },

    {
      path: '/bar',
      name: 'bar',
      component: Bar
    },
  ]
})

main.js を修正

main.js
import Vue from 'vue'
import App from './App.vue'
// 3 で作成した router モジュール
import router from './router'

Vue.config.productionTip = false

// root となる Vue インスタンスを作成する際にルーターを定義する
// 他のコンポーネントで this.$router と定義をすることで VueRouter にアクセス可能となる
new Vue({
  router,
  render: h => h(App),
}).$mount('#app')

App.vue の template の中身を修正

App.vue
<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <h1>Hello Vue.js Hands on!</h1>

    <div>
      <h2>SPA</h2>
      <!-- SPA を実現させるためには router-link コンポーネントを使用する -->
      <!-- リンク先を to プロパティに指定する -->
      <!-- router-link タグは a タグとしてレンダリングされる -->
      <router-link to="/">Go to Home</router-link><br>
      <router-link to="/foo">Go to Foo</router-link><br>
      <router-link to="/bar">Go to Bar</router-link>
    </div>

    <div>
      <h2>NOT SPA</h2>

      <a href="/">Go to Home</a><br>
      <a href="/foo">Go to Foo</a><br>
      <a href="/bar">Go to Bar</a>
    </div>

    <div>
      <h2>CONTENTS</h2>
      <!-- ルートとマッチしたコンポーネントが描画される -->
      <router-view />
    </div>
  </div>
</template>

下記のコマンドを叩いてローカルサーバーを起動

$ yarn serve

vuejs_hands_on_SPA_HOME.png

SPA の a リンクを押下しても、リロードが走らない(SPA)ことが確認可能
NOT SPA の a リンクをクリックすると通常のリクエスト、レスポンスとなり、リロードが走る

ルーターへのアクセス

this.$route でルーティング情報にアクセスすることが可能
this.$router でルーティング全体の情報にアクセスすることが可能
下記の処理は、 js の処理内で使用することが多い

// router-link で定義した a リンクをクリックすることと同義
this.$router.push('/home')

動的ルートマッチング

router.js に下記のパス情報を追加する

router.js
{
  // 「:~」と定義することで、パラメーターを含むルーティングを設定可能
  path: '/user/:id',
  name: 'user',
  component: User
}

作成した User.vue に定義する

User.vue
<template>
  <div>
    USER<br>
    <!-- url が含むパラメーターは $route.params.~ で取得可能 -->
    {{ $route.params.id }}
  </div>
</template>

名前付きルート

router.js における routes オプションの中でルートに名前を付与することが可能

router.js
routes: [
    {
      path: '/',
      name: 'home',
      component: Home
    },

    {
      path: '/foo',
      name: 'foo',
      component: Foo
    },

    {
      // 「:~」と定義することで、パラメーターを含むルーティングを設定可能
      path: '/user/:id',
      name: 'user',
      component: User
    }
 ]

router-link コンポーネントの to プロパティにオブジェクトを渡すことが可能

<router-link :to="{ name: 'user', params: { id: 123 }}">Go to User 123</router-link>

リダイレクト

router.js における routes の設定にてリダイレクトが可能
下記の記述で、 /foo から /bar にリダイレクトさせる

router.js
routes: [
  {
    path: '/foo',
    redirect: '/bar',
  }
]

上記で定義した名前付きルートに対してもリダイレクトが可能

router.js
routes: [
  {
    path: '/foo',
    redirect: { name: 'bar' },
  }
]

function を使用した動的なダイレクトも可能

router.js
routes: [
  {
    path: '/foo',
    redirect: () => {
      alert('リダイレクトします')
      return '/bar'
    },
]

ネストされたルーティング

下記のようなルーティングだった場合の実現方法

~/user/:id
~/user/:id/profile
~/user/:id/posts

router.js を修正する

router.js
{
  path: '/user/:id',
  name: 'user',
  component: User,
  children: [
    {
      // ~/user/:id/profile がマッチした際に User コンポネ内の router-view 内部で描画される
      path: 'profile',
      component: UserProfile
    },
    {
      // ~/user/:id/posts がマッチした際に User コンポネ内の router-view 内部で描画される
      path: 'posts',
      component: UserPosts
    }
  ]
}

User.vue を修正する

User.vue
<template>
  <div>
    USER
    <!-- ネストされたコンポネは下記の router-view にて描画される -->
    <router-view />
  </div>
</template>

スクロール位置を制御する

デフォルトだと SPA でページを表示した際に、スクロール位置が固定されている。
VueRouter のインスタンスを生成する際に下記の定義を追加することで、
ブラウザらしい挙動になる。

router.js
export default new VueRouter({
  .
  .
  scrollBehavior (to, from, savedPosition) {
    // ブラウザの「戻る/進む」ボタン押下時には、スクロール位置が固定される(savedPostion に定義されている)
    return savedPosition ? savedPosition : { x: 0, y: 0 }
  },
  .
  .
 }
0
1
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
0
1