JavaScript

[Vue3]vue-routerでページごとにタイトルをつける

こんにちは、Football MyTeamというサッカーアプリを作っているTsukadaです。
このアプリのフロント部分はVUe.jsで作られています。

今回はFootball MyTeamのフロント部分を作っているときに学んだ、vue-routerでページごとにタイトルをつける方法についてまとめていきます。

Vue.jsを使ってSPAを作成するとタイトルがプロジェクト名で統一されてしまいます。
なのでvue-routerを使って各ページにタイトルをつけていく必要があります。

想定している読者

  • プログラミング初心者でVue.jsを学び始めたばかり
  • 未経験からエンジニアに転職するためにポートフォリオを作成している
  • vue-routerを既に使っていて、ページ遷移はできている

vue-routerを1から解説するというわけではありません🙏

僕のアプリ環境

  • バックエンド: Ruby on Rails 6.1.5
  • Vue.js: 3.2
  • node.js 16.4
  • インフラ: Docker

参考資料

vue-router
Interface: Router

タイトル設定をする前のvue-router

以下はタイトル設定をする前のvue-router(router.js)のコードです。
そのまま載せています🙏

importしているのはページ遷移先のコンポーネントがほとんどです。
それ以外はvuer-routerを読み込んでいるだけです。

import { createRouter, createWebHistory } from 'vue-router'
import TeamList from '../components/page/TeamSelect.vue'
import CompetitorTeamSelect from '../components/page/CompetitorTeamSelect/CompetitorTeamSelect.vue'
import TeamSchedule from '../components/page/TeamSchedule/TeamSchedule.vue'
import TeamScheduleShowPage from '../components/page/TeamSchedule/TeamScheduleShowPage.vue'
import NotFound from '../components/request_error/NotFound.vue'

export const router = createRouter({
  history: createWebHistory(),
  routes: [
    {
       path: '/leagues',
       component: TeamList
     },
     {
       path: '/competitors',
       component: CompetitorTeamSelect
     },
     {
       path: '/schedules',
       component: TeamSchedule
     },
     {
       path: '/schedules/:id',
       name: 'show',
       component: TeamScheduleShowPage
     },
     {
       path: '/:pathMatch(.*)*',
       component: NotFound
     }
  ]
})

タイトルをつける手順は以下の2つです。

  • DEFALT_TITLEを定義
  • routesの設定にmeta{title: 'タイトル'}を追加する
  • 表示されたページに設定されたタイトルをdocument.titleにする

DEFALT_TITLEを定義

meta{title: 'タイトル'}で定義したタイトルじゃないページが返ってきたときに表示するタイトルを設定しておきます。

const DEFAULT_TITLE = 'Football MyTeam'

 

デフォルトのタイトルを設定しておいて想定外のことにも対応できるようにしておきます。

routesの設定にmeta{title: 'タイトル'}を追加する

では各ページにタイトルを設定していきます。
ここで設定したタイトルがタブに表示されるようになります。

先ほどのコードにタイトルを追加しました。

# importは省略

import { createRouter, createWebHistory } from 'vue-router'
import TeamList from '../components/page/TeamSelect.vue'
import CompetitorTeamSelect from '../components/page/CompetitorTeamSelect/CompetitorTeamSelect.vue'
import TeamSchedule from '../components/page/TeamSchedule/TeamSchedule.vue'
import TeamScheduleShowPage from '../components/page/TeamSchedule/TeamScheduleShowPage.vue'
import NotFound from '../components/request_error/NotFound.vue'

export const router = createRouter({
  history: createWebHistory(),
  routes: [
    {
       path: '/leagues',
       component: TeamList,
       + meta: { title: '応援しているチームを登録' }
     },
     {
       path: '/competitors',
       component: CompetitorTeamSelect,
       + meta: { title: 'ライバルチームを登録' }
     },
     {
       path: '/schedules',
       component: TeamSchedule,
       + meta: { title: '試合情報の詳細' }
     },
     {
       path: '/schedules/:id',
       name: 'show',
       component: TeamScheduleShowPage,
       + meta: { title: '試合情報の詳細' }
     },
     {
       path: '/:pathMatch(.*)*',
       component: NotFound,
       + meta: { title: 'ページが見つかりません' }
     }
  ]
})

 

ページごとの設定にmeta: { title: 'hogehoge' }を追加するだけです。

表示されたページに設定されたタイトルをdocument.titleにする

そもそもタイトルでどうやって決まるの?という疑問がありました。
この記事を書きながら調べてみたらわかったのですが、Document.titleプロパティによって現在のページのタイトルを設定または取得するそうです。

なので設定したタイトルをDocument.titleにすればよさそうです。

ということで書いたコードはこちら。

# importは省略

import { createRouter, createWebHistory } from 'vue-router'
import TeamList from '../components/page/TeamSelect.vue'
import CompetitorTeamSelect from '../components/page/CompetitorTeamSelect/CompetitorTeamSelect.vue'
import TeamSchedule from '../components/page/TeamSchedule/TeamSchedule.vue'
import TeamScheduleShowPage from '../components/page/TeamSchedule/TeamScheduleShowPage.vue'
import NotFound from '../components/request_error/NotFound.vue'

export const router = createRouter({
  history: createWebHistory(),
  routes: [
    {
       path: '/leagues',
       component: TeamList,
       meta: { title: '応援しているチームを登録' }
     },
     {
       path: '/competitors',
       component: CompetitorTeamSelect,
       meta: { title: 'ライバルチームを登録' }
     },
     {
       path: '/schedules',
       component: TeamSchedule,
       meta: { title: '試合情報の詳細' }
     },
     {
       path: '/schedules/:id',
       name: 'show',
       component: TeamScheduleShowPage,
       meta: { title: '試合情報の詳細' }
     },
     {
       path: '/:pathMatch(.*)*',
       component: NotFound,
       meta: { title: 'ページが見つかりません' }
     }
  ]
})

const DEFAULT_TITLE = 'Football MyTeam'

+ router.afterEach((to) => {
+ const title = to.meta.title
+ ? ${to.meta.title} | ${DEFAULT_TITLE}
+ : DEFAULT_TITLE
+ document.title = title
+ })

 

afterEach()はvue-routerのメソッドになります。
上記のコードでafterEachの引数に入っているtoには表示されているページのパスやparams、meta等が入っています。
このmetaは先ほど設定したページのタイトルになります。

なので上記の追加したコードは以下のように処理されています。

  • 表示されているページのタイトルと設定したタイトルが一緒ならそのタイトルをtitle変数に定義
  • 設定したタイトルと違うならDEFALT_TITLEtitle変数に定義
  • titleに定義されたものをdocument.titleとしてページのタイトルとして設定する

これで完成です。