Vue.jsでページネーションを実装

####Rails + Vue.jsを使用しています

Vue.js初心者なので分かりにくい説明だと思いますがよろしくお願いします:smiley:
##前提条件
APIを使用してJSONでデータを返している前提で書いています
分からない方は以下などを参考にすれば分かると思います
[既存のRailsアプリにJSONを返すAPIを実装してみる](https://qiita.com/kotaroooo0/items/1af71180c220e112dcd3)
[Ruby on Rails, Vue.js で始めるモダン WEB アプリケーション入門](https://qiita.com/tatsurou313/items/4f18c0d4d231e2fb55f4)

##実装

vuejs-paginateを使って実装します
準備としてmain.jsに以下を記述

##main.js

```.js
import Paginate from 'vuejs-paginate'
Vue.component('paginate', Paginate)
```

まずは全体のコード
##完成コード(TweetsPage.vue)

```.vue
<template>
  <div class="tweets">
    <div v-for="e in getLists" :key="e.id">
      {{e.id}}
      {{e.name}}
    </div>
    <paginate
      :v-model="currentPage" 
      :page-count="getPageCount"
      :click-handler="clickCallback"
      :page-range="3"
      :margin-pages="2"
      :prev-text="'＜'"
      :next-text="'＞'"
      :container-class="'pagination'"
      :page-link-class="'page-link'">
    </paginate>
  </div>
</template>
<script>
import axios from 'axios'
export default {
  data() {
    return {
      tweets: [],
      currentPage: 1,
      parPage: 10,
    }
  },
  mounted() {
    this.fetchTweets() //fetchTweetsを呼ぶ
  },
  methods: {
    fetchTweets() {
      axios
        .get(`/api/v1/tweets/tweets.json`)
        .then(response =>{
          this.tweets = response.data;
        })
    },
    clickCallback: function (pageNum) {
       this.currentPage = Number(pageNum);
    },
  },
  computed: {
     getLists: function() {
       let current = this.currentPage * this.parPage;
       let start = current - this.parPage;
       return this.tweets.slice(start, current);
     },
     getPageCount: function() {
       return Math.ceil(this.tweets.length / this.parPage);
     }
   }
}
</script>

```

####順番に簡単に解説していきます

まずはdetaの準備

```.js
import axios from 'axios'
export default {
  data() {
    return {
      tweets: [], //axiosで取ってきたデータを格納するため
      currentPage: 1, //現在いるページ
      parPage: 10, //1ページで表示するデータ数　今回は1ページにつき10個のデータを表示
    }
  }
  mounted() {
    this.fetchTweets()
  },
```

axiosというのを使ってJSONで返ってきているデータを取得してtweetsに格納

```.js
  methods: {
    fetchTweets() {
      axios
        .get(`/api/v1/tweets/index.json`) //json形式のデータが確認できるURLを記述
        .then(response =>{
          this.tweets = response.data; //dataで定義したtweetsに取ってきたデータを格納
        })
    },
```

出力したいデータを出力
そしてページネーション実装

```.js
<template>
 <div v-for="e in getLists" :key="e.id"> //Railsでいう each doのようなものでしょうか　繰り返しでgetList(この後出てくる)の返り値であるデータを全て表示
   {{e.id}}
   {{e.name}}
 </div>

 <paginate
   :v-model="currentPage" // 現在のページ
   :page-count="getPageCount" 
   :click-handler="clickCallback" //クリック(ページ移動)する度にclickCallbackを呼び出す
   :page-range="3" //3ページ以降は[...]で省力する
   :margin-pages="2" //ラスト2ページから省力しない
   :prev-text="'＜'" //戻るボタンは[<]
   :next-text="'＞'" //進むボタンは[>]
   :container-class="'pagination'"
   :page-link-class="'page-link'">
 </paginate>
</template>
```

###ページネーションの処理
現在のページを決めたり、今いるページに合ったデータだけを取得したり、全部で何ページ必要か計算したり

```.js
  //現在のページを決める処理
    clickCallback: function (pageNum) { 
       this.currentPage = Number(pageNum); //ページネーションで選択したページを現在のページにする 2ページを選択したらcurrentPageに2が代入される 3ページなら3
    },
  },
  computed: {
  //必要なデータだけを取得する処理
     getLists: function() { 
       let current = this.currentPage * this.parPage; //現在のページ×1ページに表示する数
       let start = current - this.parPage;
       return this.tweets.slice(start, current); //そのページに合ったデータだけを表示 1ページ目ならtweetsの０〜9番目を、2ページ目なら10〜19番目のデータを表示
     },
  //総ページ数を決める処理
     getPageCount: function() {
       return Math.ceil(this.tweet.length / this.parPage); //全部で何ページ必要か
     }
   }
```

後はapplication.html.erbなどにBootstrapのスタイルを適用するCDNを呼び出せば見た目が整います

```.erb
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.css">
```

このようになるのではないでしょうか？
![スクリーンショット 2021-03-01 0.40.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551832/68dbb7f0-4129-73e1-b436-739df584c750.png)

おかしな箇所があればコメントください！
最後までご高覧いただきましてありがとうございました！:laughing:

### 参考記事
[「vuejs-paginate」を使ってページネーションを実装する](https://www.kabanoki.net/4320/)