【Nuxt.js】pagination実践編:$router.pushで簡単実装!
🎈 この記事はWPへ移行しました
【Nuxt.js】pagination実践編:$router.pushで簡単実装!
# 前置き
ページ数に応じて
urlと表示が変わるpaginationです🍒
前回やった導入編と全く別物です!
こっちの方が簡単なので別パターンとして紹介🌟
記事タイトルが紛らわしいので、
まとめて名称変えるかもしれません。
こちらの続きはまた別記事にて…!
firebaseを月曜日に公開予定でしたが、
Cloud Firestoreがバグり。。。
それが落ち着いてからにします☁️
今後は火・木に投稿していく予定です!
# 構成
・pagination部分をコンポーネント化
・使用するページからpropsでdataを渡す🎁
・ページ数をurlに表示させる🔍($router.push)
・全7ページで、ページ数に応じて表示を変更
# Step1: コンポーネントでpropsを用意
【構成】
使うコンテンツによって
最大ページ数などが変わるためpropsを使用
・query: ページネーションを使うコンテンツ
・length: ページの長さ
・now: 今いるページ
【Pagination.vue】
<script>
export default {
props: {
query: {
type: String,
required: true,
},
length: {
type: Number,
required: true,
},
now: {
type: Number,
required: true,
},
},
}
</script>
# Step2: コンポーネントで戻る・進むボタンを追加
【式】三項演算を使用
式1 ? 式2 : 式3
式1がtrueなら式2、falseなら式3
【Pagination.vue】
<template>
<div>
<button
class="btn btn-prev"
@click="$router.push(`?${query}=${now - 1 || 1}`)"
>
戻る
</button>
<button
class="btn btn-next"
@click="$router.push(`?${query}=${now + 1 <= length ? now + 1 : length}`)"
>
進む
</button>
</div>
</template>
<script>
export default {
props: {
query: {
type: String,
required: true,
},
length: {
type: Number,
required: true,
},
now: {
type: Number,
required: true,
},
},
}
</script>
【解説】
◾️戻る
・|| または
該当コンテンツページ内queryの
今いるページnowから1戻る、または1にする
◾️進む
該当コンテンツページ内の
今いるページに1を足して
・全体ページ数と同じ
・またはそれより小さい場合
今いるページから1進む
そうでなければ全体ページ数にする
つまり全体ページを7で、
現在いるページが7なら
7 + 1 <= 7
falseになるので7のまま
それ以上進むことはないですね🍀
あれ?😶
【戻る】すごくシンプルに見えるのに…
@click="$router.push(`?${query}=${now - 1 || 1}`)"
【進む】は何か長い。
@click="$router.push(`?${query}=${now + 1 <= length ? now + 1 : length}`)"
これではダメなの???🌨
@click="$router.push(`?${query}=${now + 1 || length}`)"
最大ページ数を越えてどんどん進みます笑
lengthの値はマイナスにはできません。
そのため制限をかけなくても
勝手に1で止まってくれるのですが…!
プラスは制限をかけないと止まりません🏃♀️💨
# Step3: コンポーネントでページ数を表示
【構成】
ページ数の表示部分を作りましょう!
・5ページまではページ数分のみ表示
・6ページ以上は…(三点リーダー)で中間を省略
【CSS】
毎度のことですが省きます。
・…はcssでdotクラスでborderを使用
・現在ページがをクラスバインディングで
background-color, colorを変更🎨
【if, if, if…】
ifで沢山分岐しています笑
どこで並列になってるか分かりにくいですね🤔
コンパクトにして全体構造を把握しましょう。
【Pagination.vue】
主にインラインのコメントで解説!
コードでも並列部分を絵文字で区別しています。
🍀と🐥が並列で使われている部分です。
それ以外の絵文字は if の目印です!
<template>
<div
// ページ数が1より大きい、2ページ以上の時のみページネーションを表示
v-if="length > 1"
class="list-item list-item-nav"
>
<button
class="btn btn-prev"
@click="$router.push(`?${query}=${now - 1 || 1}`)"
>
戻る
</button>
<ul class="list">
// 1ページ目はどんな時でも固定表示のためif不要
<li
// クラスバインディング、{ class名: 式 }でtrueの時にクラスがつく
:class="{ now: now === 1 }"
class="item item-link"
// 1ページを押すとurlが~/1になる
@click="$router.push(`?${query}=1`)"
>
<span class="text">
1
</span>
</li>
// 🌟ここから分岐、最大ページ数が2より大きい3〜
<template v-if="length > 2">
// 🍀3以上5以下(=最大ページ数3,4,5の時)
5ページまでの場合は、最大ページ数に応じて該当ページ数を表示
<template v-if="length <= 5">
<li
:class="{ now: now === 2 }"
class="item item-link"
@click="$router.push(`?${query}=2`)"
>
<span class="text">
2
</span>
</li>
// 💭最大ページ数が3, 4, 5かつ3より大きい4, 5の時
<template v-if="length > 3">
<li
:class="{ now: now === 3 }"
class="item item-link"
@click="$router.push(`?${query}=3`)"
>
<span class="text">
3
</span>
</li>
// 🍰最大ページ数が3, 4, 5かつ3より大きい4, 5かつ4より大きい5の時
<template v-if="length > 4">
<li
:class="{ now: now === 4 }"
class="item item-link"
@click="$router.push(`?${query}=4`)"
>
<span class="text">
4
</span>
</li>
</template>
</template>
</template>
// 🍀でなければ(=最大ページが5より大きい6〜)
<template v-else>
// 🐥最大ページ6〜かつ現在いるページが4より少ない(=1, 2, 3の時)
<template v-if="now < 4">
<li
:class="{ now: now === 2 }"
class="item item-link"
@click="$router.push(`?${query}=2`)"
>
<span class="text">
2
</span>
</li>
<li
:class="{ now: now === 3 }"
class="item item-link"
@click="$router.push(`?${query}=3`)"
>
<span class="text">
3
</span>
</li>
<li
// 🍭現在いるページが4より少ないかつ、3ページ目にいる時
v-if="now === 3"
class="item item-link"
@click="$router.push(`?${query}=4`)"
>
<span class="text">
4
</span>
</li>
<li class="item item-dots">
<div class="dot" />
<div class="dot" />
<div class="dot" />
</li>
</template>
// 🐥最大ページ6〜かつ現在いるページが1, 2, 3でなく4で〜
現在いるページに2を出しても最大ページ数と同じか少なければ
(4ページ目にいるなら4 + 2、最大ページ7の方が大きいためfalse)
(6ページ目にいるなら6 + 2、最大ページ7より大きいためtrue)
<template v-else-if="length <= now + 2">
<li class="item item-dots">
<div class="dot" />
<div class="dot" />
<div class="dot" />
</li>
// 🌷最大ページ数から2を引いた数字が現在いるページだったら
最大ページ数から3を引いたページ数を表示させる
(5ページ目にいるなら7-2 =5でtrue、7-3 =4が表示される)
<li
v-if="now === length - 2"
class="item item-link"
@click="$router.push(`?${query}=${length - 3}`)"
>
<span class="text">
{{ length - 3 }}
</span>
</li>
<li
:class="{ now: now === length - 2 }"
class="item item-link"
@click="$router.push(`?${query}=${length - 2}`)"
>
<span class="text">
{{ length - 2 }}
</span>
</li>
<li
:class="{ now: now === length - 1 }"
class="item item-link"
@click="$router.push(`?${query}=${length - 1}`)"
>
<span class="text">
{{ length - 1 }}
</span>
</li>
</template>
// 🐥最大ページ6〜かつ、今までのパターンに該当しない
(上の🐥のfalse、現在4ページの場合)
<template v-else>
<li class="item item-dots">
<div class="dot" />
<div class="dot" />
<div class="dot" />
</li>
<li
class="item item-link"
@click="$router.push(`?${query}=${now - 1}`)"
>
<span class="text">
{{ now - 1 }}
</span>
</li>
<li class="item item-link now">
<span class="text">
{{ now }}
</span>
</li>
<li
class="item item-link"
@click="$router.push(`?${query}=${now + 1}`)"
>
<span class="text">
{{ now + 1 }}
</span>
</li>
<li class="item item-dots">
<div class="dot" />
<div class="dot" />
<div class="dot" />
</li>
</template>
</template>
</template>
<li
:class="{ now: now === length }"
class="item item-link"
@click="$router.push(`?${query}=${length}`)"
>
<span class="text">
{{ length }}
</span>
</li>
</ul>
<button
class="btn btn-next"
@click="$router.push(`?${query}=${now + 1 <= length ? now + 1 : length}`)"
>
進む
</button>
</div>
</template>
<script>
export default {
props: {
query: {
type: String,
required: true,
},
length: {
type: Number,
required: true,
},
now: {
type: Number,
required: true,
},
},
}
</script>
これで完成です🤗
【最大ページ2は?】
if は最大ページ3以上で分岐。
2はどうなっているかというと…
ul 内の構造を黄色い枠で分けています🐥
・1固定表示
・3ページ以上で分岐
・最大ページ固定表示
2が最大の場合は
最大ページを表示させてるわけです🌟
# Step4: コンテンツページでpropsにdataを渡す
【sample.vue】
queryはstring型のため
urlにページ数を入れたいなら
Numberに変更する必要があります。
Number($route.query.members) が
0 or falseなら1になる
・A || B
AまたはB の意味もありますが
A ? A : B 三項演算と同じでもあります!
<template>
<div class="page">
<Pagination
query="members"
:length="7"
:now="Number($route.query.members) || 1"
class="nav"
/>
</div>
</template>
<script>
import Pagination from '~/components/Pagination.vue'
export default {
components: {
Pagination,
},
data() {
return {
members: [
{
name: aLiz
},
],
}
},
}
</script>
<style lang="scss" scoped>
</style>
次回はSEOの続きか、
TypeScriptの導入あたりをやります。
公開予定日は1/23(木)です。
このアカウントでは
Nuxt.js、Vue.jsを誰でも分かるよう、
超簡単に解説しています🎈😀
これからも発信していくので、
ぜひフォローしてください♪
🎈 この記事はWPへ移行しました
【Nuxt.js】pagination実践編:$router.pushで簡単実装!
この記事が気に入ったらサポートをしてみませんか?