忘れないように記録しとこ

カバの樹

Vue.jsでフィルター機能付きのテーブルにページネーションを付ける方法

2020年1月16日

はじめに

半年前にクライアント用に、Vue.jsでフィルター付きリストページを作りました。
幸いにしてクライアントが良く使ってくれているようで、データ量が増大していきました。
開発当初は、1秒も掛からなかったページの表示(レンダリング)が、2秒、3秒とだんだん遅くなっていきました。

これはまずいと思い、ページネーションを実装することにしました。

参考
「vuejs-paginate」を使ってページネーションを実装する

「vuejs-paginate」は、ページネーションを実装するライブラリです。シンプルなAPIで提供されており、容易に実装することができます。CSSによってページネーションコンポーネントのスタイルをカスタマイズすることができます。コピペで実装できるサンプルを公開してます。

続きを見る

 

しかし、1つ問題がありました。
ページネーション付きのリストにフィルター機能を付属するにはどうしたら良いのだろう?

というわけで試しに作ってみました。

 

検証環境

Vue.js 2.6.0
vuejs-paginate
2.1.0

 

導入手順

外部ファイル

サンプルにBootstrapベースのCSSで、ページネーションにvuejs-paginateを使用します。

<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
<script src="https://unpkg.com/vuejs-paginate@2.1.0"></script>

 

HTML

リストを <table> で準備します。

<paginate> を設置してページネーションを用意します。

<div id="app">
  <h2>page {{currentPage}}</h2>
  <div>search: <input type="text" v-model="select" placeholder="ID search"></div>
  <table class="table table-bordered">
    <thead>
      <tr>
        <th>No</th>
        <th>Title</th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="item in getLists">
        <td>{{item.id}}</td>
        <td>{{item.title}}</td>
      </tr>
    </tbody>
  </table>
  <paginate
    v-model="currentPage"
    :page-count="getPageCount"
    :initial-page="4"
    :page-range="3"
    :margin-pages="2"
    :prev-text="'<'"
    :next-text="'>'"
    :container-class="'pagination'"
    :page-class="'page-item'">
  </paginate>
</div>

 

スクリプト

今回の一番重要なポイントは、フィルターの入力をされた時にwatchにて検知することです。
検知した際にページネーションの現在のページを1ページ目に変更しています。
これをしないと、現在ページだけ置いてけぼりになってしまいます。

var items = [];

for(var i=1; i<=105; i++){
  items.push({
    id: i,
    title: 'item-'+i
  });
}

Vue.component('paginate', VuejsPaginate);

new Vue({
  el: '#app',
  data: {
    select: '',
    items: items,
    parPage: 10,
    currentPage: 1
  },
  computed: {
    getItems: function() {
      let self = this;
      return this.items.filter(function(item){
        return String(item.id).indexOf(self.select) !== -1;
      });
    },
    getLists: function(){
      let current = this.currentPage * this.parPage;
      let start = current - this.parPage;
      return this.getItems.slice(start, current);
    },
    getPageCount: function() {
      return Math.ceil(this.getItems.length / this.parPage);
    }
  },
  watch:{
    select: function(){
      this.currentPage = 1;
    }
  }
});

 

サンプル

>>専用ページで確認する

 

最後に

フィルター機能付きのテーブルにページネーションを付ける方法でした。

 

今日はこの辺でー

 

  • B!