かめ。ブログ

ページネーションの処理をする関数

2022年8月1日
2022年8月1日

目次

ページネーションを自前で作る時用メモ。
ページネーションを作ろうかと考えていた時に、下記の記事を見つけて参考にして作りました。

参考



ページネーション関数

function pagination (current: number, lastNum: number) {
  const DELTA: number = 2
  const range: number[] = []
  const rangeWithDots: (number | '...')[] = []

  let left = Math.max(1, current - DELTA)
  let right = Math.min(lastNum, current + DELTA)
  const lostNum = Math.abs(Math.abs(left - right) - DELTA * 2)
  if (lostNum > 0) {
    if (left === 1) {
      right += lostNum
    } else if (right === lastNum) {
      left -= lostNum
    }
  }

  for (let i: number = 1; i <= lastNum; i++) {
    if (i === 1 || i === lastNum || (i >= left && i <= right)) {
      range.push(i)
    }
  }

  let l: number | undefined
  for (const i of range) {
    if (l && (i - l === 2 || i - l !== 1)) {
      rangeWithDots.push('...')
    }
    rangeWithDots.push(i)
    l = i
  }


  return rangeWithDots
}


構造に関しての説明は、参考のサイトに詳しく書かれていたので少し割愛します。

試すためのコード

for (let i = 1, l = 20; i <= l; i++) {
  console.log(`Selected page ${i}:`, pagination(i, l));
}


Selected page 1: 1,2,3,4,5,...,20
Selected page 2: 1,2,3,4,5,...,20
Selected page 3: 1,2,3,4,5,...,20
Selected page 4: 1,2,3,4,5,6,...,20
Selected page 5: 1,...,3,4,5,6,7,...,20
Selected page 6: 1,...,4,5,6,7,8,...,20
Selected page 7: 1,...,5,6,7,8,9,...,20
Selected page 8: 1,...,6,7,8,9,10,...,20
Selected page 9: 1,...,7,8,9,10,11,...,20
Selected page 10: 1,...,8,9,10,11,12,...,20
Selected page 11: 1,...,9,10,11,12,13,...,20
Selected page 12: 1,...,10,11,12,13,14,...,20
Selected page 13: 1,...,11,12,13,14,15,...,20
Selected page 14: 1,...,12,13,14,15,16,...,20
Selected page 15: 1,...,13,14,15,16,17,...,20
Selected page 16: 1,...,14,15,16,17,18,...,20
Selected page 17: 1,...,15,16,17,18,19,20
Selected page 18: 1,...,16,17,18,19,20
Selected page 19: 1,...,16,17,18,19,20
Selected page 20: 1,...,16,17,18,19,20


参考にさせていただいたコードから、自分なりに改良した部分

  let left = Math.max(1, current - DELTA)
  let right = Math.min(lastNum, current + DELTA)
  const lostNum = Math.abs(Math.abs(left - right) - DELTA * 2)
  if (lostNum > 0) {
    if (left === 1) {
      right += lostNum
    } else if (right === lastNum) {
      left -= lostNum
    }
  }


参考にさせていただいたコードは、下記のように端っこにきた時に表示位置によって表示されている数字の個数が変動していました。

Selected page 19: 1, "...", 17, 18, 19, 20
Selected page 20: 1, "...", 18, 19, 20


その部分を端っこにきた場合でも最低限の数字は減らないように調整しました。

Selected page 19: 1,...,16,17,18,19,20
Selected page 20: 1,...,16,17,18,19,20


こうすることで数字がページによって変動することがなくなるので、レイアウトがガクッとすることがなくなります。

まとめ

これを使って、実際にVueやReactでコンポーネントを作ってはあるのですが
それはまた別の機会に解説できればなと思います。



関連する記事