飴屋

Vue.js/リストを改良した

ページングした

前回、複数ある項目をリスト表示して、件数を数えて、絞り込み機能をつけました。絞り込まれたリスト(filteredRows)が現在の表示対象です。全部で6件あるデータ(rows - filteredRows)を2件ずつ表示するページング機能(rows - filteredRows - pagedRows)を作ってみましょう。

const app = Vue.createApp({
  data() {
    return {
      rows: [ .. ],
      page: 0,
      per: 10,
      ...
    }
  },
  computed: {
    filteredRows() { .. },
    pagedRow() {
      return this.filteredRows.slice(this.page*this.per,this.page*this.per+this.per);
    },
  }
});
app.mount('#list');

data部にページングされた何ページ目を表示されるかを表す page と1ページにいくつデータを表示するかを表す per という項目を足しました。pageは0始まりなので初期値は0です。6件のデータを1ページ2件、3ページに分けるのでperは2です。
computed部のpagedRowはfilteredRowsから選択されたページ(page)のデータを抜き出して返します。

これで最初の1ページ目が表示されるようになりました・・・が、次のページに移動できません。pageデータを変更する操作部を作りましょう。

操作部

const app = Vue.createApp({
  data() { .. },
  computed: { .. },
  methods: {
    pageList() {
      const n = this.pageNumber()+1;
      const c = this.page+1;
      let list = [],to = false;
      for (let x=1;x<=n;x++) {
        if (
          x === 1 ||
          x === n ||
          (c <= 4 && x <= 5) ||
          (c > 4 && c <= n - 4 && (c - 1 <= x && x <= c + 1)) ||
          (c > n - 4 && x >= n - 4)
        ) {
          list.push(x);
          to = false;
        } else if (!to) {
          list.push(-1);
          to = true;
        }
      }
      return list;
    },
    pageNumber() {
      return Math.floor((this.filteredRows.length-1)/this.per);
    },
    prevPage() {
      if (this.page>0) this.movePage(this.page-1);
    },
    nextPage() {
      if (this.page+1<=this.pageNumber()) this.movePage(this.page+1);
    },
    movePage(p) {
      this.page = p;
    },
  }
});
app.mount('#list');

methods部にpageListというのを用意しました。これを呼び出した場所にページ番号の選択肢の配列を返します。番号が多すぎて画面がぐちゃぐちゃにならないように、よくある中間を間引く処理もついています。

pageNumberはページの数を返すメソッドで、指定のページに移動するのがmovePage、前後のページに移動するのがそれぞれprevPagenextPageです。page値を書き換えるだけで描画してくれるので楽ちん!

<div class="paging">
	<span class="prev" v-if="page != 0" @click="prevPage">←</span>
	<span class="numbers">
		<span v-for="p in pageList()" :class="pageClass(p)" @click="movePage(p-1)">{{ p==-1 ? '…' : p }}</span>
	</span>
	<span class="next" v-if="page != pageNumber()" @click="nextPage">→</span>
</div>

HTML側はこんな感じにしてみました。番号列の前後にはクリックすると一つ前のページ、一つ後ろのページに移動する要素も置いてあります。

computedでデータを整形して、操作するUIをつけてあげる・・・こういうのを役割に応じていじる部分が固まっているのが、製作を楽にしてくれるんでしょうね。保守性はまだわかんないですけど。

Vue.js記事一覧