前置き
ページ数に応じて
urlと表示が変わるpaginationです🍒
前回やった導入編と全く別物です!
こっちの方が簡単なので別パターンとして紹介🌟
記事タイトルが紛らわしいので、
まとめて名称変えるかもしれません。
こちらの続きはまた別記事にて…!
構成
・pagination部分をコンポーネント化
・使用するページからpropsでdataを渡す🎁
・ページ数をurlに表示させる🔍($router.push)
・全7ページで、ページ数に応じて表示を変更
Step1: コンポーネントでpropsを用意
【構成】
使うコンテンツによって
最大ページ数などが変わるためpropsを使用
・query: ページネーションを使うコンテンツ
・length: ページの長さ
・now: 今いるページ
) components
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<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
) components
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
<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のまま
それ以上進むことはないですね🍀
あれ?😶
【戻る】すごくシンプルに見えるのに…
1 |
@click="$router.push(`?${query}=${now - 1 || 1}`)" |
【進む】は何か長い。
1 |
@click="$router.push(`?${query}=${now + 1 <= length ? now + 1 : length}`)" |
これではダメなの???🌨
1 |
@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 の目印です!
) components
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
<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を渡す
【index.vue】
queryはstring型のため
urlにページ数を入れたいなら
Numberに変更する必要があります。
Number($route.query.members) が
0 or falseなら1になる
・A || B
AまたはB の意味もありますが
A ? A : B 三項演算と同じでもあります!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<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> |