この記事は最終更新日から 2 年以上が経過しており、内容が古くなっている可能性があります。
Nuxt.js にページネーションを付けるために、Vue.js のパッケージVuejs-paginateを導入した。
導入方法
Vuejs-paginate に限らず、Nuxt.js で外部パッケージを追加するとwindow is not defined
のエラーが出るので、plugin を作成してグローバルコンポーネントとして登録する。
import Vue from "vue";
import Paginate from "vuejs-paginate";
Vue.component("paginate", Paginate);
plugins: [
{src: '~/plugins/vuejs-paginate', ssr:false },
],
プラグインの build オプションを client でのみ実行するように設定する。Nuxt.js 2.14.x 以降はmode:'cliant'
といった記述方法が非推奨になったため、ssr:false
とする。
ページネーションメソッドの設定
<script>
export default {
data() {
return {
items: "",
parPage: "",
currentPage: "",
};
},
methods: {
clickCallback: function (pageNum) {
this.currentPage = Number(pageNum);
},
},
computed: {
posts: function () {
let current = this.currentPage * this.parPage;
let start = current - this.parPage;
return this.items.slice(start, current);
},
getPageCount: function () {
return Math.ceil(this.items.length / this.parPage);
},
},
async asyncData({ $content }) {
const items = await $content("post").sortBy("published", "desc").fetch();
const parPage = 12;
const currentPage = 1;
return { items, parPage, currentPage };
},
};
</script>
data プロパティ
items
…アイテムの配列。nuxt/content で記事を作成している当ブログの場合は post フォルダ内から取得している。parPage
…1 ページに表示するアイテム数currentPage
…現在のページ番号(1 から始まる)
methods
clickCallback
…ページネーションクリック時にcurrentPage
へページ番号を設定
computed
posts
…現在のページのアイテムを返す。当ブログの場合はCard
コンポーネントへも渡している。getPageCount
…ページネーションの最大ページ数(items
をparPage
で割って切り上げ)
テンプレート部分
<template>
<main role="main">
<CardList :posts="posts" />
<client-only placeholder="Loading...">
<paginate
v-if="(getPageCount > 1)"
:page-count="getPageCount"
:page-range="3"
:margin-pages="2"
:click-handler="clickCallback"
:prev-text="'前へ'"
:next-text="'次へ'"
:container-class="'pagination flex justify-center mb-6'"
:page-class="'c-pagination-item'"
:page-link-class="'c-pagination-item__link'"
:prev-class="'c-pagination-btn c-pagination-prev'"
:prev-link-class="'c-pagination-btn__link'"
:next-class="'c-pagination-btn c-pagination-next'"
:next-link-class="'c-pagination-btn__link'"
:hide-prev-next="true"
>
</paginate>
</client-only>
</main>
</template>
以下は当ブログ独自に追加したもの
<client-only placeholder="Loading..."> </client-only>
の部分はwindow is not defined
エラー対策。v-if="(getPageCount > 1)"
…デフォルトだと 1 ページのみの場合もページネーションが出てしまうので、2 ページ以上の時に表示されるようにするための処理。
プロパティ
当ブログで使用しているものを抜粋
名前 | タイプ | 説明 |
---|---|---|
page-count |
数値 | 総ページ数(必須)。上記テンプレートの場合getPageCount に渡されている。 |
page-range |
数値 | 表示されるページ数(アクティブページの前後に同じページ数表示されるようにするため、奇数推奨)。デフォルト値:3 |
margin-pages |
数値 | 余白のページ表示数。デフォルト値:1 |
prev-text |
文字列 | 「前へ」ボタンのテキスト。HTML使用可。デフォルト値:prev |
next-text |
文字列 | 「次へ」ボタンテキスト。HTML使用可。デフォルト値:next |
click-handler |
関数 | ページをクリックした時に呼び出すメソッド。クリックされたページ番号をパラメーターとして使用する。 |
container-class |
文字列 | ページネーションを囲むコンテナのclass |
page-class |
文字列 | ページ要素のliタグのclass |
page-link-class |
文字列 | ページ要素のaタグのclass |
prev-class |
文字列 | 「前へ」ボタン要素liタグのclass |
prev-link-class |
文字列 | 「前へ」ボタン要素aタグのclass |
next-class |
文字列 | 「次へ」ボタン要素liタグのclass |
next-link-class |
文字列 | 「次へ」ボタン要素aタグのclass |
hide-prev-next |
真偽 | 前/次のページがない場合はボタンを表示しない。デフォルト値:false (表示) |
CSS でスタイルを当てる
container-class
には tailwindcss のflex
justify-center
mb-6
の class が当てられているので、それ以外のパーツを css で装飾する。
.c-pagination-btn__link,
.c-pagination-item__link {
border: solid 2px #3a3f58;
border-radius: 4px;
text-align: center;
padding: 0.5rem 1rem;
margin: 0 0.25rem;
display: block;
}
.c-pagination-btn__link:hover,
.c-pagination-item__link:hover {
background-color: #3a3f58;
color: #fff;
}
.active .c-pagination-item__link {
background-color: #3a3f58;
color: #fff;
pointer-events: none;
}