前置き
データ量の多いページで活躍する
ページネーション💫
以前にも解説しましたが、
もっとシンプルに分かりやすくしました🙌
まずは全体の構成を考えて枠組みを作って
そこから作り込む流れにしています✨
⬇️以前の解説記事はこちら
【Nuxt.js】pagination導入編:まずは大枠を理解しよう!
【Nuxt.js】pagination実践編:$router.pushで簡単実装!
全体の構成を考える
コンポーネント
数字などのまとまりなので
アトミックデザインのmolecules
で分類しています。
分け方、命名は参考程度にしてください🍀molecules/Items/ItemPagination.vue
デザインの確認
まずは作りたいものを確認🌱👀
数字部分
現在いるページに合わせて
数字が…になったりします。
ただ1は固定で1なので
2以降の数字だけ
条件に合わせて
数字なのか…なのかを
指定する必要があります。
矢印
左右の矢印は
現在いるページ(now
)が
最初のページ(now === 1
)か
最後のページ(totalPage
)なら
隣の矢印を透明にするclass
名(inactive
)を
付与すれば良いです。
遷移先
nuxt-link to=""
の遷移先は
URLのquery
を使用したいのでquery
というprops
を使って
親で文字列を指定するようにします。
query
やnow
などの変数と?
や=
という文字列を連結させたいので
テンプレートリテラルを使用します。
バッククォーテーションの中に${変数}
で繋げていきます。
URLのquery
は?
から始まるので
このような感じになります。
1 2 |
<nuxt-link to="`?${query}=${now - 1 || 1 }">1つ前</nuxt-link> <nuxt-link to="`?${query}=1`">1</nuxt-link> |
⬇️params
, query
はこちらでご確認ください👀
localhost:3000/product?page=123
?
より前のproduct
がparams
?page=123
がquery
です
【Nuxt.js】Vue Router基礎編:params, queryを使ってページ遷移
⬇️できれば遷移した時に
いちいち上にスクロールするのが面倒なので
v-sroll-toを使うと尚よしです✨
【Nuxt.js】plugin実践編:vue-scrolltoをページ遷移でも適応させよう
コード
スタイリングにまで書くと
コードが長くなって分かりにくいので
解説を読んでclass
名と役割を把握してください👀
1についているcurrent
クラスは
現在いるページだけ
色を反転させるようにするものです🌟
矢印はsvg画像を1つ用意し、
左右反転させています。transform: scale(-1, 1);
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 |
<template> <ul v-if="totalPage > 1" class="item item-pagination"> // 左矢印 <li class="item"> <nuxt-link :to="`?${query}=${now - 1 || 1}`" :class="{ inactive: now === 1 }" class="item-link prev" > <svg viewBox="0 0 24 24" class="icon"> <use xlink:href="#i-arrow" /> </svg> </nuxt-link> </li> // 数字の1は固定表示 <li class="item"> <nuxt-link :to="`?${query}=1`" :class="{ current: now === 1 }" class="item-link" > 1 </nuxt-link> </li> // 数字の2以降、…なのか数字になるのか条件を指定 <template v-if="totalPage >= 2"> <template v-if="totalPage <= 5"> </template> <template v-else> </template> </template> // 右矢印 <li class="item"> <nuxt-link :to="`?${query}=${now + 1 <= totalPage ? now + 1 : totalPage}`" :class="{ inactive: now === totalPage }" class="item-link next" > <svg viewBox="0 0 24 24" class="icon"> <use xlink:href="#i-arrow" /> </svg> </nuxt-link> </li> </ul> </template> <script> export default { props: { totalPage: { type: Number, required: true, }, query: { type: String, required: true, }, now: { type: Number, required: true, }, }, } </script> |
現在いるページについて
全体の構成がわかったところで
数字の2以降は一旦おいておき、
現在いるページ(now
)はどう出すのか
仕組みを把握しておきましょう🪐
親ページ
ページネーションを表示させる親ページでは
こんな感じのコードになります。
リストのデータはListProducts
というコンポーネントだとします。
limit
(1ページに表示させるliの数)
などはおいといて、:now="Number()"
部分を見てみましょう。$route.query
は
localhost:3000/?page=2
なら{"page": "2"}
になりますね💡
現在いるページに必要な情報は
ページ数の2
だけで良いので$route.query[query]
とすることでquery(Stringのpage)
に対応する2
をNumber
で数値として返しているわけです。
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> <ListProducts :products=" products.slice( (Number($route.query[query] || 1) - 1) * limit, (Number($route.query[query] || 1) - 1) * limit + limit ) " /> <ItemPagination :total-page="parseInt((products.length + limit - 1) / limit)" :query="query" :now="Number($route.query[query] || 1)" /> </template> <script> export default { props: { products: { type: Array, required: true, }, }, data() { return { query: 'page', limit: 12, } }, } </script> |
数字の2以降のコード
nowの仕組みがわかったところで
ページネーションに戻りましょう。
矢印と1は邪魔なので
2以降の部分のみコードを載せます。
※最終的なコードは最後に載せています💫
⬇️totalPageが6以上でnowが3未満
⬇️totalPageからnowを引いて2未満
⬇️それ以外
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 |
<template> <ul v-if="totalPage > 1" class="item item-pagination"> // totalPageが1の時は2以降は必要ないため <template v-if="totalPage >= 2"> // totalPageが5以下の時は…が不要なのでtotalPage数に合わせて5まで書く <template v-if="totalPage <= 5"> <li class="item"> <nuxt-link :to="`?${query}=2`" :class="{ current: now === 2 }" class="item-link" > 2 </nuxt-link> </li> <template v-if="totalPage >= 3"> <li class="item"> <nuxt-link :to="`?${query}=3`" :class="{ current: now === 3 }" class="item-link" > 3 </nuxt-link> </li> </template> <template v-if="totalPage >= 4"> <li class="item"> <nuxt-link :to="`?${query}=4`" :class="{ current: now === 4 }" class="item-link" > 4 </nuxt-link> </li> </template> <template v-if="totalPage >= 5"> <li class="item"> <nuxt-link :to="`?${query}=5`" :class="{ current: now === 5 }" class="item-link" > 5 </nuxt-link> </li> </template> </template> // totalPageが6以上の時 <template v-else> // 現在いるページが3未満(1or 2)の時は「23…」 <template v-if="now < 3"> <li class="item"> <nuxt-link :to="`?${query}=2`" :class="{ current: now === 2 }" class="item-link" > 2 </nuxt-link> </li> <li class="item"> <nuxt-link :to="`?${query}=3`" :class="{ current: now === 3 }" class="item-link" > 3 </nuxt-link> </li> <li class="item"> <p class="item-dot item-link">...</p> </li> </template> // totalPageからnowを引いて2未満(1)つまりtotalPageの1個前にいる時は「…とtotalPage-2」 <template v-else-if="totalPage - now < 2"> <li class="item"> <p class="item-dot item-link">...</p> </li> <li class="item"> <nuxt-link :to="`?${query}=${totalPage - 2}`" :class="{ current: now === totalPage - 2 }" class="item-link" > {{ totalPage - 2 }} </nuxt-link> </li> </template> // それ以外の間にいる時は「…数字3つ…」 <template v-else> <li class="item"> <p class="item-dot item-link">...</p> </li> <li class="item"> <nuxt-link :to="`?${query}=${now - 1}`" class="item-link"> {{ now - 1 }} </nuxt-link> </li> <li class="item"> <nuxt-link :to="`?${query}=${now}`" class="item-link"> {{ now }} </nuxt-link> </li> <li class="item"> <nuxt-link :to="`?${query}=${now + 1}`" class="item-link"> {{ now + 1 }} </nuxt-link> </li> <li v-if="totalPage - now > 2" class="item"> <p class="item-dot item-link">...</p> </li> </template> // totalPage数 <li class="item"> <nuxt-link :to="`?${query}=${totalPage}`" :class="{ current: now === totalPage }" class="item-link" > {{ totalPage }} </nuxt-link> </li> </template> </template> </ul> </template> |
まとめ
デザインを確認しながら
不要なコードはたたみながらやると
把握しやすいです✨
特に数字と…の切り替えをするところは
どこが並列で何の入れ子なのか
ハッキリさせることが大事ですね💡