環境
Nuxt.js 2.14.0
nuxt-jsonld 1.5.2
パンくずリストのコンポーネントを作成
まずはコンポーネントを作成します。
HTMLを作成
まずはHTMLを書きましょう。
コードをシンプルに保つためCSSについては割愛します。
componentsディレクトリの配下にBreadcrumb.vueというファイルを作成して、下記のように3階層目にいることを想定してHTMLを書いていきます。
<template>
<nav aria-label="パンくずリスト">
<ol>
<li>
<nuxt-link to="#!">ホーム</nuxt-link>
</li>
<li>
<nuxt-link to="#!">ブログ</nuxt-link>
</li>
<li>
<span aria-current="page">ブログタイトル</span>
</li>
</ol>
</nav>
</template>
navタグにaria-labelでパンくずリストの役割を持っているHTMLであることを明示して、現在地を示すテキストにはaria-currentを入れています。
一旦パンくずを表示させるためにpages/index.vueあたり(表示できればlayoutでもどこでも良いです)に差し込んで表示を確認しましょう。
<template>
<div>
<Breadcrumb />
</div>
</template>
nuxt.config.js
でcomponents: true
としていればimport文を書かなくても自動でコンポーネントをインポートしてくれるようになるので設定しておくのがおすすめです。
参考:The components Property – Nuxt.js
export default {
components: true,
}
v-forでコードを整理
data()
でパンくずリストのオブジェクトの配列を定義して、v-forを使ってコードをリファクタします。
nuxt-linkとspanタグの出し分けは次でやるので、一旦2つずつ表示されてしまいますが、そのまま書いておきましょう。
<template>
<nav aria-label="パンくずリスト">
<ol>
<li v-for="(item, index) in breadcrumbs" :key="index">
<nuxt-link :to="item.path" v-text="item.name" />
<span aria-current="page" v-text="item.name" />
</li>
</ol>
</nav>
</template>
<script>
export default {
name: 'Breadcrumb',
data() {
return {
breadcrumbs: [
{
name: 'ホーム',
path: '/',
},
{
name: 'ブログ',
path: '/blog/',
},
{
name: 'タイトル',
path: '',
},
],
}
},
}
</script>
最後の要素のpathは使わないので空にしましたが、書いても大丈夫です。
nuxt-linkタグとspanタグを分岐する関数を作成
上の階層はリンク付きで、現在地はリンクなしのパンくずリストにしたいので、if文で分岐をさせて出し分けをします。
現在地=配列の最後の要素ということなので、v-forのindexを引数として配列の最後の要素と比較してBoolean型で返す関数を作成します。
methods: {
isCurrentPage(index) {
return this.breadcrumbs.length - 1 === index
},
},
関数を作成できたらspanタグとnuxt-linkタグをそれぞれtemplateタグで囲って、span側のtemplateタグにv-if="isCurrentPage(index)"
を、nuxt-linkタグ側のtemplateタグにv-else
を追加します。
<template>
...
<li v-for="(item, index) in breadcrumbs" :key="index">
<template v-if="isCurrentPage(index)">
<span aria-current="page" v-text="item.name" />
</template>
<template v-else>
<nuxt-link
:to="item.path"
v-text="item.name"
/>
</template>
</li>
...
</template>
<script>
export default {
...,
methods: {
isCurrentPage(index) {
return this.breadcrumbs.length - 1 === index
},
},
}
</script>
ここまでうまく表示できているか確認しておきましょう。
pages側からpropsで値を渡す
今のままだとパンくずリスト内で直接dataを定義して固定のテキストを表示しているだけなのでコンポーネントとして使い回すことができませんね。
ページごとに表示させたいデータはページが持つべきなのでpages/index.vue
でデータを作成してpropsでコンポーネントに渡すようにしましょう。
components/Breadcrumb.vue
のdeta()で定義したbreadcrumbsをpages/index.vue
に持ってきましょう。
(表示確認のため3階層のまま使います。)
<template>
<div>
<Breadcrumb />
</div>
</template>
<script>
export default {
data() {
return {
breadcrumbs: [
{
name: 'ホーム',
path: '/',
},
{
name: 'ブログ',
path: '/blog/',
},
{
name: 'タイトル',
path: '',
},
],
}
},
}
</script>
components/Breadcrumb.vue
でpropsを定義して、
export default {
props: {
lists: {
type: Array,
required: true,
},
},
}
pages/index.vue
で定義したデータを受け取れるようにします。
<template>
<div>
<Breadcrumb :lists="breadcrumbs" />
</div>
</template>
components/Breadcrumb.vue
で使うデータの名前が変わったので修正します。
liのv-forとisCurrentPage関数で使用していたbreadcrumbsをlistsに変更します。
<template>
...
<li v-for="(item, index) in lists" :key="index">
<template v-if="isCurrentPage(index)">
<span aria-current="page" v-text="item.name" />
</template>
<template v-else>
<nuxt-link
:to="item.path"
v-text="item.name"
/>
</template>
</li>
...
</template>
<script>
export default {
...,
methods: {
isCurrentPage(index) {
return this.lists.length - 1 === index
},
},
}
</script>
これでパンくずリストコンポーネントは完成です!
パンくずリストコンポーネント完成形のコード
部分的に説明してわかりにくかった部分もあったと思うので、ここまでの完成形のコードを記載します。
JSON-LDに対応せず、WAI-AREAのみで良ければこれで完成となります!
<template>
<nav aria-label="パンくずリスト">
<ol>
<li v-for="(item, index) in lists" :key="index">
<template v-if="isCurrentPage(index)">
<span aria-current="page" v-text="item.name" />
</template>
<template v-else>
<nuxt-link
:to="item.path"
v-text="item.name"
/>
</template>
</li>
</ol>
</nav>
</template>
<script>
export default {
name: 'Breadcrumb',
props: {
lists: {
type: Array,
required: true,
},
},
methods: {
isCurrentPage(index) {
return this.lists.length - 1 === index
},
},
}
</script>
nuxt-jsonldのインストールと設定
続いてJSON-LDに対応するため、nuxt-jsonldモジュールを使いましょう。
nuxt-jsonldのインストール
npmからインストールします。
nuxt-jsonld – npm
$ npm install nuxt-jsonld
// or
$ yarn add nuxt-jsonld
プラグインの作成と設定
インストールができたらプラグインを作成します。
plugins/jsonld.js
を作成して、下記のように記載しましょう。
import Vue from 'vue'
import NuxtJsonld from 'nuxt-jsonld'
Vue.use(NuxtJsonld)
続いて作成したプラグインをnuxt.config.jsで登録します。
export default {
...,
plugins: ['~/plugins/jsonld'],
}
ここまで出来たらNuxtプロジェクトを再起動します。
(再起動しないとうまく出力されないことがあるので気をつけてください。)
JSON-LDを出力
ここまででJSON-LDを使う準備が整ったので、実際に出力してみましょう。
パンくずリストのオブジェクトにURLを追加
まずはJSON-LDで出力するURLですが、httpから始まる絶対パスでの指定となりますので、ページ側のパンくずリストのオブジェクトにURLを追加します。
ドメインは適宜変更してください。
<script>
export default {
data() {
return {
breadcrumbs: [
{
name: 'ホーム',
path: '/',
url: 'https://xxx.com/',
},
{
name: 'ブログ',
path: '/blog/',
url: 'https://xxx.com/blog/',
},
{
name: 'テストテスト',
path: '',
url: `https://xxx.com${this.$route.path}`,
},
],
}
},
}
</script>
idによってURLが変わる、動的ルーティングをしているときには上記のようにthis.$route.path
を指定すると現在のパスを取得できます。
JSON-LDを出力する関数を追加
続いて、components/Breadcrumb.vue
のscript内にJSON-LDを出力する関数を追記していきます。
export default {
...,
jsonld() {
const items = this.lists.map((item, index) => ({
'@type': 'ListItem',
position: index + 1,
item: {
'@id': item.url,
name: item.name,
},
}))
return {
'@context': 'http://schema.org',
'@type': 'BreadcrumbList',
itemListElement: items,
}
},
}
うまく出来ていればheadに出力されているので検証ツールで確認してみましょう。
完成時の全体のコード
ここまでの全体のコードです。
うまくできなかったという方は比較してみてください。
<template>
<nav aria-label="パンくずリスト">
<ol>
<li v-for="(item, index) in lists" :key="index">
<template v-if="isCurrentPage(index)">
<span aria-current="page" v-text="item.name" />
</template>
<template v-else>
<nuxt-link
:to="item.path"
v-text="item.name"
/>
</template>
</li>
</ol>
</nav>
</template>
<script>
export default {
name: 'Breadcrumb',
props: {
lists: {
type: Array,
required: true,
},
},
methods: {
isCurrentPage(index) {
return this.lists.length - 1 === index
},
},
jsonld() {
const items = this.lists.map((item, index) => ({
'@type': 'ListItem',
position: index + 1,
item: {
'@id': item.url,
name: item.name,
},
}))
return {
'@context': 'http://schema.org',
'@type': 'BreadcrumbList',
itemListElement: items,
}
},
}
</script>
ページ側のデータは下記の形式です。ページによって変更してください。
<template>
<div>
<Breadcrumb :lists="breadcrumbs" />
</div>
</template>
<script>
export default {
data() {
return {
breadcrumbs: [
{
name: 'ホーム',
path: '/',
url: 'https://xxx.com/',
},
{
name: '第二階層',
path: '/second/',
url: 'https://xxx.com/second/',
},
{
name: '第三階層',
path: '/third/', // 空でもOK
url: 'https://xxx.com/second/third/',
},
],
}
},
}
</script>