Nuxtの動的ルーティングで一覧画面のページングに共通のVueファイルを使う
- 投稿した日
- 更新した日
- 書いたひと
- ひらたけ
ブログなどを構築する際、投稿の一覧画面にページングの機能を実装することがよくあると思います。Nuxt で実装しているウェブサイトで一覧画面の 1 ページ目を「/blog
」、2 ページ目以降を「/blog/page/2
」としたい場合に、/pages
ディレクトリに配置した共通の Vue ファイルを使用しようとして詰まったので、解決方法を備忘録的に残しておこうと思います。
環境
実装時に使用した Nuxt などのバージョンは以下のとおりです。
「Nuxt ページング」「Nuxt ページネーション」とかで検索すると、Nuxt 3 じゃなくて Nuxt 2 の記事がたくさん出てきてわりと困りました。Nuxt 3 がリリースされてからもう 1 年半くらい経ってるはずですが、まだ Nuxt 2 を使ってるひと多いんだろうか…。
やりたいこと
以下の URL にアクセスした場合に、/pages
ディレクトリに配置した共通の Vue ファイルが呼び出されるようにします。
/blog
/blog/page/2
/blog/page/3
実装方法
Nuxt のドキュメント にある「Dynamic Routes」の 2 重角括弧を使用します。ドキュメントによると /pages/[[slug]].vue
は /
と /test
の両方に一致する、つまり [[slug]]
を任意にすることができます。
これを使用して、/pages/blog/[[slug]]/[[page]].vue
というファイルを作成することで /blog
と /blog/page/2
や /blog/page/3
などに一致するようになります。
root/
├ pages/
│ └ blog/
│ └ [[slug]]
│ └ [[page]].vue
├ package.json
└ nuxt.config.ts
これで、一覧画面の 1 ページ目と 2 ページ目以降で共通の Vue ファイルを使用することができました。
ただ、このままだと /blog/hoge
や /blog/hoge/fuga
といった関係のない URL でアクセスした場合も読まれてしまうので、別途関係のない URL の場合に 404 エラーとする、みたいな処理が必要になります。
/blog
以下にあるブログの投稿ページなどの URL がどのようになっているかにもよりますが、以下みたいな感じになると思います。
<script lang="ts" setup>
const route = useRoute()
const { data, error } = await useAsyncData(
route.path,
() => {
// /blog もしくは /blog/page/<1~9から始まる数字>
if (!/^\/blog(\/page\/[1-9]\d*)?\/?$/.test(route.path)) {
throw new Error('URLの形式が不正です')
}
// 記事を取得する処理など
return ...
}
)
if (error.value) {
throw createError({
statusCode: 404,
message: error.value.message,
fatal: true,
})
}
</script>
めちゃくちゃ余談ですけど、正規表現使うとき ChatGPT とか Copilot に質問すると代わりに考えてくれるので良いですね。「JavaScript で使える形式にして」みたいな指示もできるし。